Project

General

Profile

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

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

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

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

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

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

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

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

    
44
/* include all configuration functions */
45

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

    
49
	$sasyncd_text = "";
50

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
197
				/* step through each phase2 entry */
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
						$pfd = fopen("/var/db/ipsecpinghosts", "a");
211
						$iflist = get_configured_interface_list();
212
						foreach ($iflist as $ifent => $ifname) {
213
							$interface_ip = get_interface_ip($ifent);
214
							$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
215
							if (ip_in_subnet($interface_ip, $local_subnet))
216
								$srcip = $interface_ip;
217
						}
218
						$dstip = $ph2ent['pinghost'];
219
						fwrite($pfd, "$srcip|$dstip|3\n");
220
						fclose($pfd);
221
					}
222
				}
223
			}
224
		}
225

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

    
254
		$pskconf = "";
255

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
343
					$net_list = '';
344

    
345
					foreach ($a_phase2 as $ph2ent) {
346

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
427
					switch ($myid_type) {
428

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

    
434
						case "dyn_dns":
435
							$myid_type = "address";
436
							$myid_data = gethostbyname($ph1ent['myid_data']);
437
							break;
438

    
439
						case "address";
440
							$myid_data = $ph1ent['myid_data'];
441
							break;
442

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

    
453
					$peerid_type = $ph1ent['peerid_type'];
454

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

    
461
						case "address";
462
							$peerid_data = $ph1ent['peerid_data'];
463
							break;
464

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

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

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

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

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

    
499
					$certline = '';
500

    
501
					if (strstr($authmethod,'rsa')) {
502

    
503
						$cert = lookup_cert($ph1ent['certref']);
504

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

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

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

    
520
						chmod($certpath, 0600);
521

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

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

    
531
						chmod($keypath, 0600);
532

    
533
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
534
					}
535

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

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

    
548
					/* add remote section to configuration */
549

    
550
					$racoonconf .=<<<EOD
551

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

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

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

    
587
				/* begin sainfo */
588
				foreach ($a_phase2 as $ph2ent) {
589

    
590
					$ikeid = $ph2ent['ikeid'];
591

    
592
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
593
						continue;
594

    
595
					if (isset($ph1ent['disabled']))
596
						continue;
597

    
598
					if (isset($ph2ent['disabled']))
599
						continue;
600

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

    
604
					if ($ph2ent['mode'] == 'tunnel') {
605

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

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

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

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

    
623
					} else {
624

    
625
						$rgip = $rgmap[$ph1ent['remote-gateway']];
626

    
627
						$localid_data = ipsec_get_phase1_src($ph1ent);
628
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
629
						$localid_spec = "address {$localid_data}";
630

    
631
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
632
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
633
						$remoteid_spec = "address {$remoteid_data}";
634
					}
635

    
636
					if($ph2ent['protocol'] == 'esp') {
637

    
638
						$ealgos = '';
639

    
640
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
641

    
642
							$ealg_id = $ealg['name'];
643
							$ealg_kl = $ealg['keylen'];
644

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

    
680
						$ealgosline = "encryption_algorithm {$ealgos};";
681

    
682
					} else {
683

    
684
						$ealgosline = "encryption_algorithm null_enc;";
685
					}
686

    
687
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
688
					$halgosline = "authentication_algorithm {$halgos};";
689

    
690
					$pfsline = '';
691
					if ($ph2ent['pfsgroup'])
692
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
693
					if (isset($a_client['pfs_group'])) {
694
						$pfsline = '';
695
						if ($a_client['pfs_group'])
696
							$pfsline = "pfs_group {$a_client['pfs_group']};";
697
					}
698

    
699
					$lifeline = '';
700
					if ($ph2ent['lifetime'])
701
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
702

    
703
					/* add sainfo section to configuration */
704
					
705
					$racoonconf .=<<<EOD
706
					
707
sainfo {$localid_spec} {$remoteid_spec}
708
{
709
	remoteid {$ikeid};
710
	{$ealgosline}
711
	{$halgosline}
712
	{$pfsline}
713
	{$lifeline}
714
	compression_algorithm deflate;
715
}
716

    
717
EOD;
718
				}
719
				/* end sainfo */
720
			}
721
			/* end sainfo sections */
722

    
723
			fwrite($fd, $racoonconf);
724
			fclose($fd);
725
		}
726
		/* end racoon.conf */
727

    
728
		/* generate IPsec policies */
729
		if (is_array($a_phase2) && count($a_phase2)) {
730
			/* generate spd.conf */
731
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
732
			if (!$fd) {
733
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
734
				return 1;
735
			}
736

    
737
			$spdconf = "";
738

    
739
			/* What are these SPD entries for?
740
			 * -mgrooms 07/10/2008
741
			 */
742
			$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
743
			$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
744

    
745
			foreach ($a_phase2 as $ph2ent) {
746

    
747
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
748
					continue;
749

    
750
				if (isset($ph1ent['mobile']))
751
					continue;
752

    
753
				if (isset($ph1ent['disabled']))
754
					continue;
755

    
756
				if (isset($ph2ent['disabled']))
757
					continue;
758

    
759
				$ep = ipsec_get_phase1_src($ph1ent);
760
				if (!$ep)
761
					continue;
762

    
763
				$rgip = $rgmap[$ph1ent['remote-gateway']];
764

    
765
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
766
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
767

    
768
				if (isset ($ph2ent['creategif'])) {
769
					$number_of_gifs = find_last_gif_device();
770
					$number_of_gifs++;
771
					$curwanip = get_interface_ip();
772
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
773
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
774
							if ($sasyncd['ip'] <> "")
775
								$curwanip = $sasyncd['ip'];
776
						}
777
					}
778
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
779
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
780
				}
781

    
782
				if($ph2ent['mode'] == "tunnel") {
783

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

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

    
790
				} else {
791

    
792
					$localid_data = ipsec_get_phase1_src($ph1ent);
793
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
794

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

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

    
801
				}
802

    
803
				/* static route needed? */
804
				if (preg_match("/^carp/i", $ph1ent['interface']))
805
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
806
				else
807
					$parentinterface = $ph1ent['interface'];
808

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

    
834
			fwrite($fd, $spdconf);
835
			fclose($fd);
836
		}
837

    
838
		/* needed for racoonctl admin socket */
839
		if (!is_dir("/var/db/racoon"))
840
			mkdir("/var/db/racoon/");
841
		
842
		exec("/bin/mkdir -p /var/db/racoon");
843

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

    
863
			/* start dnswatch, if necessary */
864
			if (count($dnswatch_list) > 0) {
865
				$interval = 60;
866
				if ($ipseccfg['dns-interval'])
867
					$interval = $ipseccfg['dns-interval'];
868

    
869
				$hostnames = "";
870
				array_unique($dnswatch_list);
871
				$hostnames = implode("\n", $dnswatch_list);
872
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
873

    
874
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
875
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
876
			}
877
		}
878
	
879
		vpn_ipsec_failover_configure();
880

    
881
		if ($g['booting'])
882
			echo "done\n";
883
	}
884

    
885
	return 0;
886
}
887

    
888
/* Forcefully restart IPsec
889
 * This is required for when dynamic interfaces reload
890
 * For all other occasions the normal vpn_ipsec_configure()
891
 * will gracefully reload the settings without restarting
892
 */
893
function vpn_ipsec_force_reload() {
894
	global $config;
895
	global $g;
896

    
897
	$ipseccfg = $config['ipsec'];
898

    
899
	/* kill racoon */
900
	if(is_process_running("racoon"))
901
		mwexec("/usr/bin/killall racoon", true);
902

    
903
	/* wait for process to die */
904
	sleep(4);
905

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

    
909
	/* wait for flushing to finish */
910
	sleep(1);
911

    
912
	/* if ipsec is enabled, start up again */
913
	if (isset($ipseccfg['enable'])) {
914
		log_error("Forcefully reloading IPsec racoon daemon");
915
		vpn_ipsec_configure();
916
	}
917

    
918
}
919

    
920
/* master setup for vpn (mpd) */
921
function vpn_setup() {
922
	/* start pptpd */
923
	vpn_pptpd_configure();
924

    
925
	/* start pppoe server */
926
	vpn_pppoe_configure();
927

    
928
	/* setup l2tp */
929
	vpn_l2tp_configure();
930
}
931

    
932
function vpn_pptpd_configure() {
933
	global $config, $g;
934

    
935
	$syscfg = $config['system'];
936
	$pptpdcfg = $config['pptpd'];
937

    
938
	if ($g['booting']) {
939
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
940
			return 0;
941

    
942
		echo "Configuring PPTP VPN service... ";
943
	} else {
944
		/* kill mpd */
945
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
946

    
947
		/* wait for process to die */
948
		sleep(3);
949

    
950
		if (is_process_running("mpd -b")) {
951
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
952
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
953
		}
954

    
955
		/* remove mpd.conf, if it exists */
956
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
957
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
958
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
959
	}
960

    
961
	/* make sure pptp-vpn directory exists */
962
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
963
		mkdir("{$g['varetc_path']}/pptp-vpn");
964

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

    
974
			$mpdconf = <<<EOD
975
pptpd:
976

    
977
EOD;
978

    
979
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
980
				$mpdconf .= "	load pt{$i}\n";
981
			}
982

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

    
985
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
986

    
987
				$mpdconf .= <<<EOD
988

    
989
pt{$i}:
990
	new -i pptpd{$i} pt{$i} pt{$i}
991
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
992
	load pts
993

    
994
EOD;
995
			}
996

    
997
			$mpdconf .=<<<EOD
998

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

    
1019
EOD;
1020

    
1021
			if (!isset ($pptpdcfg['req128'])) {
1022
				$mpdconf .=<<<EOD
1023
	set ccp yes mpp-e40
1024
	set ccp yes mpp-e56
1025

    
1026
EOD;
1027
			}
1028

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

    
1044
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1045
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1046
				$acctport = $authport + 1;
1047
				$mpdconf .=<<<EOD
1048
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1049

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

    
1057
EOD;
1058
			}
1059
			$mpdconf .=<<<EOD
1060
	set radius retries 3
1061
	set radius timeout 10
1062
	set auth enable radius-auth
1063

    
1064
EOD;
1065

    
1066
				if (isset ($pptpdcfg['radius']['accounting'])) {
1067
					$mpdconf .=<<<EOD
1068
	set auth enable radius-acct
1069
	set radius acct-update 300
1070

    
1071
EOD;
1072
				}
1073
			}
1074

    
1075
			fwrite($fd, $mpdconf);
1076
			fclose($fd);
1077

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

    
1085
			$mpdlinks = "";
1086

    
1087
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1088
				$mpdlinks .=<<<EOD
1089

    
1090
pt{$i}:
1091
	set link type pptp
1092
	set pptp enable incoming
1093
	set pptp disable originate
1094
	set pptp disable windowing
1095

    
1096
EOD;
1097
			}
1098

    
1099
			fwrite($fd, $mpdlinks);
1100
			fclose($fd);
1101

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

    
1109
			$mpdsecret = "";
1110

    
1111
			if (is_array($pptpdcfg['user'])) {
1112
				foreach ($pptpdcfg['user'] as $user)
1113
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1114
			}
1115

    
1116
			fwrite($fd, $mpdsecret);
1117
			fclose($fd);
1118
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1119

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

    
1123
			break;
1124

    
1125
		case 'redir' :
1126
			break;
1127
	}
1128

    
1129
	if ($g['booting'])
1130
		echo "done\n";
1131

    
1132
	return 0;
1133
}
1134

    
1135
function vpn_pppoe_configure() {
1136
	global $config, $g;
1137

    
1138
	$syscfg = $config['system'];
1139
	$pppoecfg = $config['pppoe'];
1140

    
1141
	/* create directory if it does not exist */
1142
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1143
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1144

    
1145
	if ($g['booting']) {
1146
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1147
			return 0;
1148

    
1149
		echo "Configuring PPPoE VPN service... ";
1150
	} else {
1151
		/* kill mpd */
1152
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1153

    
1154
		/* wait for process to die */
1155
		sleep(2);
1156

    
1157
	}
1158

    
1159
	/* make sure pppoe-vpn directory exists */
1160
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1161
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1162

    
1163
	switch ($pppoecfg['mode']) {
1164

    
1165
		case 'server' :
1166

    
1167
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1168

    
1169
			if ($pppoecfg['paporchap'] == "chap")
1170
				$paporchap = "set link enable chap";
1171
			else
1172
				$paporchap = "set link enable pap";
1173

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

    
1184
EOD;
1185

    
1186
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1187
				$mpdconf .= "	load pppoe{$i}\n";
1188
			}
1189

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

    
1192
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1193

    
1194
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1195
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1196
				} else {
1197
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1198
				}
1199

    
1200
				$mpdconf .=<<<EOD
1201

    
1202
pppoe{$i}:
1203
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1204
	{$isssue_ip_type}
1205
	load pppoe_standart
1206

    
1207
EOD;
1208
			}
1209

    
1210
			$mpdconf .=<<<EOD
1211

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

    
1238
EOD;
1239

    
1240
			if (isset ($config['dnsmasq']['enable'])) {
1241
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1242
				if ($syscfg['dnsserver'][0])
1243
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1244
				$mpdconf .= "\n";
1245
			} else
1246
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1247
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1248
				}
1249

    
1250
			if (isset ($pppoecfg['radius']['enable'])) {
1251
				$mpdconf .=<<<EOD
1252
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
1253
	set radius retries 3
1254
	set radius timeout 10
1255
	set auth enable radius-auth
1256

    
1257
EOD;
1258

    
1259
				if (isset ($pppoecfg['radius']['accounting'])) {
1260
					$mpdconf .=<<<EOD
1261
	set auth enable radius-acct
1262

    
1263
EOD;
1264
				}
1265
			}
1266

    
1267
			fwrite($fd, $mpdconf);
1268
			fclose($fd);
1269

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

    
1277
			$mpdlinks = "";
1278

    
1279
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1280
				$mpdlinks .=<<<EOD
1281
			
1282
pppoe{$i}:
1283
	set phys type pppoe
1284
        set pppoe iface {$pppoe_interface}
1285
        set pppoe service "*"
1286
        set pppoe disable originate
1287
        set pppoe enable incoming
1288

    
1289
EOD;
1290
			}
1291

    
1292
			fwrite($fd, $mpdlinks);
1293
			fclose($fd);
1294

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

    
1302
			$mpdsecret = "\n\n";
1303

    
1304
			if (is_array($pppoecfg['user'])) {
1305
				foreach ($pppoecfg['user'] as $user)
1306
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1307
			}
1308

    
1309
			fwrite($fd, $mpdsecret);
1310
			fclose($fd);
1311
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1312

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

    
1316
			break;
1317

    
1318
		case 'redir' :
1319
			break;
1320
	}
1321

    
1322
	if ($g['booting'])
1323
		echo "done\n";
1324

    
1325
	return 0;
1326
}
1327

    
1328
function vpn_l2tp_configure() {
1329
	global $config, $g;
1330

    
1331
	$syscfg = $config['system'];
1332
	$l2tpcfg = $config['l2tp'];
1333

    
1334
	/* create directory if it does not exist */
1335
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1336
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1337

    
1338
	if ($g['booting']) {
1339
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1340
			return 0;
1341

    
1342
		echo "Configuring l2tp VPN service... ";
1343
	} else {
1344
		/* kill mpd */
1345
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1346

    
1347
		/* wait for process to die */
1348
		sleep(8);
1349

    
1350
	}
1351

    
1352
	/* make sure l2tp-vpn directory exists */
1353
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1354
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1355

    
1356
	switch ($l2tpcfg['mode']) {
1357

    
1358
		case 'server' :
1359
			if ($l2tpcfg['paporchap'] == "chap")
1360
				$paporchap = "set link enable chap";
1361
			else
1362
				$paporchap = "set link enable pap";
1363

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

    
1374
EOD;
1375

    
1376
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1377
				$mpdconf .= "	load l2tp{$i}\n";
1378
			}
1379

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

    
1382
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1383

    
1384
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1385
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1386
				} else {
1387
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1388
				}
1389

    
1390
				$mpdconf .=<<<EOD
1391

    
1392
l2tp{$i}:
1393
	new l2tp{$i} l2tp{$i}
1394
	{$isssue_ip_type}
1395
	load l2tp_standard
1396

    
1397
EOD;
1398
			}
1399

    
1400
			$mpdconf .=<<<EOD
1401

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

    
1418
EOD;
1419

    
1420
			if (isset ($config['dnsmasq']['enable'])) {
1421
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1422
				if ($syscfg['dnsserver'][0])
1423
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1424
				$mpdconf .= "\n";
1425
			} else
1426
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1427
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1428
				}
1429

    
1430
			if (isset ($l2tpcfg['radius']['enable'])) {
1431
				$mpdconf .=<<<EOD
1432
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1433
	set radius retries 3
1434
	set radius timeout 10
1435
	set auth enable radius-auth
1436

    
1437
EOD;
1438

    
1439
				if (isset ($l2tpcfg['radius']['accounting'])) {
1440
					$mpdconf .=<<<EOD
1441
	set auth enable radius-acct
1442

    
1443
EOD;
1444
				}
1445
			}
1446

    
1447
			fwrite($fd, $mpdconf);
1448
			fclose($fd);
1449

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

    
1457
			$mpdlinks = "";
1458

    
1459
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1460
				$mpdlinks .=<<<EOD
1461

    
1462
l2tp{$i}:
1463
	set link type l2tp
1464
        set l2tp enable incoming
1465
        set l2tp disable originate
1466

    
1467
EOD;
1468
			if (!empty($l2tpcfg['secret']))
1469
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1470
			}
1471

    
1472
			fwrite($fd, $mpdlinks);
1473
			fclose($fd);
1474

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

    
1482
			$mpdsecret = "\n\n";
1483

    
1484
			if (is_array($l2tpcfg['user'])) {
1485
				foreach ($l2tpcfg['user'] as $user)
1486
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1487
			}
1488

    
1489
			fwrite($fd, $mpdsecret);
1490
			fclose($fd);
1491
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1492

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

    
1496
			break;
1497

    
1498
		case 'redir' :
1499
			break;
1500
	}
1501

    
1502
	if ($g['booting'])
1503
		echo "done\n";
1504

    
1505
	return 0;
1506
}
1507

    
1508
/* Walk the tunnels for hostname endpoints. If the hostnames 
1509
 * resolve to a different IP now compared to the DNS cache
1510
 * we reload the policies if the endpoint has changed */
1511
function vpn_ipsec_refresh_policies() {
1512
	global $config;
1513
	global $g;
1514

    
1515
	$ipseccfg = $config['ipsec'];
1516
	$a_phase1 = $config['ipsec']['phase1'];
1517
	$a_phase2 = $config['ipsec']['phase2'];
1518

    
1519
	if (isset($ipseccfg['disable'])) {
1520
		return true;
1521
	}
1522

    
1523
	/* Walk the Ipsec tunnel array */
1524
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1525
		return;
1526
	}
1527

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

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

    
1576
/* reloads the tunnel configuration for a tunnel item
1577
 * Will remove and add SPD polices */
1578
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1579
	global $config;
1580
	global $g;
1581

    
1582
	/* if we are not passed a old tunnel array we create one */
1583
	if(empty($old_phase1)) {
1584
		$old_phase1 = $phase1;
1585
	}
1586
	if(empty($old_phase2)) {
1587
		$old_phase2 = $phase2;
1588
	}
1589

    
1590
	$sad_arr = ipsec_dump_sad();
1591

    
1592
	$ep = ipsec_get_phase1_src($phase1);
1593
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1594
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1595

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

    
1599
	$old_ep = ipsec_get_phase1_src($old_phase1);
1600
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1601
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1602

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

    
1620
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1621
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1622
	}
1623
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1624
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1625
	}
1626

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

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

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

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

    
1672
	$now = time();
1673
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1674
	/* generate temporary spd.conf */
1675
	file_put_contents($spdfile, $spdconf);
1676
	return true;
1677
}
1678

    
1679
?>
(44-44/50)