Project

General

Profile

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

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

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

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

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

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

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

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

    
44
/* include all configuration functions */
45

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

    
49

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

    
70
		file_put_contents("{$g['varetc_path']}/sasyncd.conf", $sasyncd_text);
71
		chmod("{$g['varetc_path']}/sasyncd.conf", 0600);
72

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
260
		$pskconf = "";
261

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

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

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

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

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

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

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

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

    
294
		/* Add user PSKs */
295
		foreach ($config['system']['user'] as $user) {
296
			if (!empty($user['ipsecpsk'])) {
297
				$pskconf .= "{$user['name']}\t{$user['ipsecpsk']}\n";
298
			}
299
		}
300

    
301
		/* add PSKs for mobile clients */
302
		if (is_array($ipseccfg['mobilekey'])) {
303
			foreach ($ipseccfg['mobilekey'] as $key) {
304
				$pskconf .= "{$key['ident']}\t{$key['pre-shared-key']}\n";
305
			}
306
		}
307

    
308
		fwrite($fd, $pskconf);
309
		fclose($fd);
310
		chmod("{$g['varetc_path']}/psk.txt", 0600);
311
			
312
		/* begin racoon.conf */
313
		if ((is_array($a_phase1) && count($a_phase1)) ||
314
			(is_array($a_phase2) && count($a_phase2))) {
315

    
316
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
317
			if (!$fd) {
318
				printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
319
				return 1;
320
			}
321

    
322
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
323
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
324
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
325

    
326
			/* begin listen section */
327
			if (count($ipmap)) {
328
				$racoonconf .= "\nlisten\n";
329
				$racoonconf .= "{\n";
330
				$racoonconf .= "	adminsock \"/var/db/racoon/racoon.sock\" \"root\" \"wheel\" 0660;\n";
331
				foreach ($ipmap as $addr) {
332
					$racoonconf .= "\tisakmp {$addr} [500];\n";
333
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
334
				}
335
				$racoonconf .= "}\n\n";
336
			}
337

    
338
			/* begin mode_cfg section */
339
			if (is_array($a_client) && isset($a_client['enable'])) {
340

    
341
				$racoonconf .= "\nmode_cfg\n";
342
				$racoonconf .= "{\n";
343

    
344
				if ($a_client['user_source'])
345
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
346
				if ($a_client['group_source'])
347
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
348

    
349
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
350
					$pool_address = $a_client['pool_address'];
351
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
352

    
353
					$pool_address = long2ip32(ip2long($pool_address)+1);
354
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
355

    
356
					$racoonconf .= "\tpool_size {$pool_size};\n";
357
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
358
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
359
				}
360

    
361
				if (isset($a_client['net_list'])) {
362

    
363
					$net_list = '';
364

    
365
					foreach ($a_phase2 as $ph2ent) {
366

    
367
						if (isset($ph2ent['disabled']))
368
							continue;
369

    
370
						if (!isset($ph2ent['mobile']))
371
							continue;
372

    
373
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
374

    
375
						if ($net_list)
376
							$net_list .= ", ";
377
						$net_list .= $localid;
378
					}
379

    
380
					if ($net_list)
381
						$racoonconf .= "\tsplit_network include {$net_list};\n";
382
				}
383

    
384
				if ($a_client['dns_server1'])
385
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
386
				if ($a_client['dns_server2'])
387
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
388
				if ($a_client['dns_server3'])
389
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
390
				if ($a_client['dns_server4'])
391
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
392

    
393
				if ($a_client['wins_server1'])
394
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
395
				if ($a_client['wins_server2'])
396
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
397

    
398
				if ($a_client['dns_domain'])
399
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
400

    
401
				if ($a_client['pfs_group'])
402
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
403

    
404
				if ($a_client['login_banner']) {
405
					$fn = "{$g['varetc_path']}/racoon.motd";
406
					$fd1 = fopen($fn, "w");
407
					if (!$fd1) {
408
						printf("Error: cannot open server{$fn} in vpn.\n");
409
						return 1;
410
					}
411

    
412
					fwrite($fd1, $a_client['login_banner']);
413
					fclose($fd1);
414

    
415
					$racoonconf .= "\tbanner \"{$fn}\";\n";
416
				}
417

    
418
				$racoonconf .= "}\n\n";
419
			}
420
			/* end mode_cfg section */
421

    
422
			/* begin remote sections */
423
			if (is_array($a_phase1) && count($a_phase1)) {
424
				/* begin remote */
425
				foreach ($a_phase1 as $ph1ent) {
426

    
427
					if (isset($ph1ent['disabled']))
428
						continue;
429

    
430
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
431
						continue;
432

    
433
					$ikeid = $ph1ent['ikeid'];
434

    
435
					$ep = ipsec_get_phase1_src($ph1ent);
436
					if (!$ep)
437
						continue;
438

    
439
					if (!isset($ph1ent['mobile'])) {
440
						$rgip = $rgmap[$ph1ent['remote-gateway']];
441
						if (!$rgip)
442
							continue;
443
					}
444

    
445
					$myid_type = $ph1ent['myid_type'];
446

    
447
					switch ($myid_type) {
448

    
449
						case "myaddress":
450
							$myid_type = "address";
451
							$myid_data = $ep;
452
							break;
453

    
454
						case "dyn_dns":
455
							$myid_type = "address";
456
							$myid_data = gethostbyname($ph1ent['myid_data']);
457
							break;
458

    
459
						case "address";
460
							$myid_data = $ph1ent['myid_data'];
461
							break;
462

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

    
473
					$peerid_type = $ph1ent['peerid_type'];
474

    
475
					switch ($peerid_type) {
476
						case "peeraddress":
477
							$peerid_type = "address";
478
							$peerid_data = $rgip;
479
							break;
480

    
481
						case "address";
482
							$peerid_data = $ph1ent['peerid_data'];
483
							break;
484

    
485
						case "fqdn";
486
						case "keyid tag";
487
						case "user_fqdn";
488
						case "asn1dn";
489
							$peerid_data = $ph1ent['peerid_data'];
490
							if( $peerid_data )
491
								$peerid_data = "\"".$peerid_data."\"";
492
							break;
493
					}
494

    
495
					$natt = "off";
496
					if (isset($ph1ent['nat_traversal']))
497
						$natt = $ph1ent['nat_traversal'];
498

    
499
					$init = "on";
500
					$genp = "off";
501
					$pcheck = "claim";
502
					$passive = "";
503
					if (isset($ph1ent['mobile'])) {
504
						$rgip = "anonymous";
505
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
506
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
507
							$passive = "passive on;";
508
							$pcheck = "obey";
509
							$genp = "on";
510
						} else {
511
							$init = "off";
512
							$genp = "unique";
513
						}
514
					}
515

    
516
					$dpdline1 = '';
517
					$dpdline2 = '';
518
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
519
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
520
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
521
					}
522

    
523
					if (isset ($ph1ent['authentication_method']))
524
						$authmethod = $ph1ent['authentication_method'];
525
					else
526
						$authmethod = 'pre_shared_key';
527

    
528
					$certline = '';
529

    
530
					if (strstr($authmethod,'rsa')) {
531

    
532
						$cert = lookup_cert($ph1ent['certref']);
533

    
534
						if (!$cert)
535
						{
536
							log_error("Error: Invalid phase1 certificate reference for {$ph1ent['name']}");
537
							continue;
538
						}
539

    
540
						$certfile = "cert-".$ikeid.".crt";
541
						$certpath = $g['varetc_path']."/".$certfile;
542

    
543
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
544
						{
545
							log_error("Error: Cannot write phase1 certificate file for {$ph1ent['name']}");
546
							continue;
547
						}
548

    
549
						chmod($certpath, 0600);
550

    
551
						$keyfile = "cert-".$ikeid.".key";
552
						$keypath = $g['varetc_path']."/".$keyfile;
553

    
554
						if (!file_put_contents($keypath, base64_decode($cert['prv'])))
555
						{
556
							log_error("Error: Cannot write phase1 key file for {$ph1ent['name']}");
557
							continue;
558
						}
559

    
560
						chmod($keypath, 0600);
561

    
562
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
563
					}
564

    
565
					$ealgos = '';
566
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
567
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
568
					if ($ealg_kl)
569
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
570
					else
571
						$ealgos = $ealgos.$ealg_id;
572

    
573
					$lifeline = '';
574
					if ($ph1ent['lifetime'])
575
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
576

    
577
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
578
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
579
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
580
					}
581

    
582
					/* add remote section to configuration */
583

    
584
					$racoonconf .=<<<EOD
585

    
586
remote {$rgip}
587
{
588
	ph1id {$ikeid};
589
	exchange_mode {$ph1ent['mode']};
590
	my_identifier {$myid_type} {$myid_data};
591
	{$peerid_spec}
592
	ike_frag on;
593
	generate_policy = {$genp};
594
	initial_contact = {$init};
595
	nat_traversal = {$natt};
596
	{$certline}
597
	{$dpdline1}
598
	{$dpdline2}
599
	support_proxy on;
600
	proposal_check {$pcheck};
601
	{$passive}
602

    
603
	proposal
604
	{
605
		authentication_method {$authmethod};
606
		encryption_algorithm ${ealgos};
607
		hash_algorithm {$ph1ent['hash-algorithm']};
608
		dh_group {$ph1ent['dhgroup']};
609
		${lifeline}
610
	}
611
}
612

    
613
EOD;
614
				}
615
				/* end remote */
616
			}
617
			/* end remote sections */
618
		
619
			/* begin sainfo sections */
620
			if (is_array($a_phase2) && count($a_phase2)) {
621

    
622
				/* begin sainfo */
623
				foreach ($a_phase2 as $ph2ent) {
624

    
625
					$ikeid = $ph2ent['ikeid'];
626

    
627
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
628
						continue;
629

    
630
					if (isset($ph1ent['disabled']))
631
						continue;
632

    
633
					if (isset($ph2ent['disabled']))
634
						continue;
635

    
636
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
637
						continue;
638

    
639
					if ($ph2ent['mode'] == 'tunnel') {
640

    
641
						$localid_type = $ph2ent['localid']['type'];
642
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
643
						/* Do not print localid in some cases, such as a pure-psk mobile tunnel */
644
						if (($localid_type == "none") || ($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))
645
							$localid_spec = " ";
646
						else if ($localid_type != "address") {
647
							$localid_type = "subnet";
648
							$localid_spec = $localid_type." ".$localid_data." any";
649
						}
650

    
651
						if (!isset($ph2ent['mobile'])) {
652
							$remoteid_type = $ph2ent['remoteid']['type'];
653
							if ($remoteid_type != "address")
654
								$remoteid_type = "subnet";
655

    
656
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
657
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
658
						} else
659
							$remoteid_spec = "anonymous";
660

    
661
					} else {
662

    
663
						$rgip = $rgmap[$ph1ent['remote-gateway']];
664

    
665
						$localid_data = ipsec_get_phase1_src($ph1ent);
666
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
667
						$localid_spec = "address {$localid_data}";
668

    
669
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
670
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
671
						$remoteid_spec = "address {$remoteid_data}";
672
					}
673

    
674
					if($ph2ent['protocol'] == 'esp') {
675

    
676
						$ealgos = '';
677

    
678
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
679

    
680
							$ealg_id = $ealg['name'];
681
							$ealg_kl = $ealg['keylen'];
682

    
683
							if ($ealg_kl) {
684
								if( $ealg_kl == "auto" ) {
685
									/*   This seems to be required on my system and was not reproducable
686
									 *   on other systems.   For some reason $p2_ealgos is not defined
687
									 *   and needs to be read back in!?  -sullrich Aug 26, 2009 
688
									 */
689
									if(!$p2_ealgos)
690
										require("ipsec.inc");
691
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
692
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
693
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
694
									/* in some cases where include ordering is suspect these variables
695
									   are somehow 0 and we enter this loop forever and timeout after 900
696
									   seconds wrecking bootup */
697
									if($key_hi != 0 and $key_lo !=0 and $key_step !=0) {
698
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
699
//											Uncomment the next line if you want to test the comment 5 lines up.											
700
//											echo "$keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step \n";
701
											if ($ealgos)
702
												$ealgos = $ealgos.", ";
703
											$ealgos = $ealgos.$ealg_id." ".$keylen;
704
										}
705
									}
706
								} else {
707
									if ($ealgos)
708
										$ealgos = $ealgos.", ";
709
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
710
								}
711
							} else {
712
								if ($ealgos)
713
									$ealgos = $ealgos.", ";
714
								$ealgos = $ealgos.$ealg_id;
715
							}
716
						}
717

    
718
						$ealgosline = "encryption_algorithm {$ealgos};";
719

    
720
					} else {
721

    
722
						$ealgosline = "encryption_algorithm null_enc;";
723
					}
724

    
725
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
726
					$halgosline = "authentication_algorithm {$halgos};";
727

    
728
					$pfsline = '';
729
					if ($ph2ent['pfsgroup'])
730
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
731
					if (isset($a_client['pfs_group'])) {
732
						$pfsline = '';
733
						if ($a_client['pfs_group'])
734
							$pfsline = "pfs_group {$a_client['pfs_group']};";
735
					}
736

    
737
					$lifeline = '';
738
					if ($ph2ent['lifetime'])
739
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
740

    
741
					/* add sainfo section to configuration */
742
					
743
					$racoonconf .=<<<EOD
744
					
745
sainfo {$localid_spec} {$remoteid_spec}
746
{
747
	remoteid {$ikeid};
748
	{$ealgosline}
749
	{$halgosline}
750
	{$pfsline}
751
	{$lifeline}
752
	compression_algorithm deflate;
753
}
754

    
755
EOD;
756
				}
757
				/* end sainfo */
758
			}
759
			/* end sainfo sections */
760

    
761
			fwrite($fd, $racoonconf);
762
			fclose($fd);
763
		}
764
		/* end racoon.conf */
765

    
766
		/* generate IPsec policies */
767
		if (is_array($a_phase2) && count($a_phase2)) {
768
			/* generate spd.conf */
769
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
770
			if (!$fd) {
771
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
772
				return 1;
773
			}
774

    
775
			$spdconf = "";
776

    
777
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
778
			if ($config['interfaces']['lan']) {
779
				$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
780
				$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
781
			}
782

    
783
			foreach ($a_phase2 as $ph2ent) {
784

    
785
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
786
					continue;
787

    
788
				if (isset($ph1ent['mobile']))
789
					continue;
790

    
791
				if (isset($ph1ent['disabled']))
792
					continue;
793

    
794
				if (isset($ph2ent['disabled']))
795
					continue;
796

    
797
				$ep = ipsec_get_phase1_src($ph1ent);
798
				if (!$ep)
799
					continue;
800

    
801
				$rgip = $rgmap[$ph1ent['remote-gateway']];
802

    
803
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
804
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
805

    
806
				if (isset ($ph2ent['creategif'])) {
807
					$number_of_gifs = find_last_gif_device();
808
					$number_of_gifs++;
809
					$curwanip = get_interface_ip();
810
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
811
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
812
							if ($sasyncd['ip'] <> "")
813
								$curwanip = $sasyncd['ip'];
814
						}
815
					}
816
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
817
					if ($config['interfaces']['lan'])
818
						mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
819
				}
820

    
821
				if($ph2ent['mode'] == "tunnel") {
822

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

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

    
829
				} else {
830

    
831
					$localid_data = ipsec_get_phase1_src($ph1ent);
832
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
833

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

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

    
840
				}
841

    
842
				/* static route needed? */
843
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
844
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
845
				else
846
					$parentinterface = $ph1ent['interface'];
847

    
848
				if ($parentinterface <> "wan") {
849
					/* add endpoint routes to correct gateway on interface */
850
					if (interface_has_gateway($parentinterface)) {
851
						$gatewayip = get_interface_gateway("$parentinterface");
852
						$interfaceip = get_interface_ip($parentinterface);
853
						$subnet_bits = get_interface_subnet($parentinterface);
854
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
855
						/* if the remote gateway is in the local subnet, then don't add a route */
856
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
857
							if(is_ipaddr($gatewayip)) {
858
								/* FIXME: does adding route-to and reply-to on the in/outbound
859
								 * rules fix this? smos@ 13-01-2009 */
860
								log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
861
								mwexec("/sbin/route delete -host {$rgip}");
862
								mwexec("/sbin/route add -host {$rgip} {$gatewayip}");
863
							}
864
						}
865
					}
866
				} else {
867
					if(stristr($route_str, "{$rgip}")) {
868
						mwexec("/sbin/route delete -host {$rgip}", true);
869
					}
870
				}
871
			}
872

    
873
			fwrite($fd, $spdconf);
874
			fclose($fd);
875
		}
876

    
877
		/* needed for racoonctl admin socket */
878
		if (!is_dir("/var/db/racoon"))
879
			mkdir("/var/db/racoon/");
880
		
881
		/* mange racoon process */
882
		if (is_process_running("racoon")) {
883
			sleep("0.1");
884
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
885
			/* load SPD without flushing to be safe on config additions or changes. */
886
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
887
		} else {
888
			/* flush SA + SPD entries */
889
			mwexec("/usr/local/sbin/setkey -FP", false);
890
 			sleep("0.1");
891
			mwexec("/usr/local/sbin/setkey -F", false);
892
 			sleep("0.1");
893
//			exec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
894
 			/* start racoon */
895
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
896
 			sleep("0.1");
897
 			/* load SPD */
898
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
899

    
900
			/* start dnswatch, if necessary */
901
			if (count($dnswatch_list) > 0) {
902
				$interval = 60;
903
				if ($ipseccfg['dns-interval'])
904
					$interval = $ipseccfg['dns-interval'];
905

    
906
				$hostnames = "";
907
				array_unique($dnswatch_list);
908
				$hostnames = implode("\n", $dnswatch_list);
909
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
910

    
911
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
912
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
913
			}
914
		}
915
	
916
		vpn_ipsec_failover_configure();
917

    
918
		if ($g['booting'])
919
			echo "done\n";
920
	}
921

    
922
	return 0;
923
}
924

    
925
/* Forcefully restart IPsec
926
 * This is required for when dynamic interfaces reload
927
 * For all other occasions the normal vpn_ipsec_configure()
928
 * will gracefully reload the settings without restarting
929
 */
930
function vpn_ipsec_force_reload() {
931
	global $config;
932
	global $g;
933

    
934
	$ipseccfg = $config['ipsec'];
935

    
936
	/* kill racoon */
937
	if(is_process_running("racoon"))
938
		mwexec("/usr/bin/killall racoon", true);
939

    
940
	/* wait for process to die */
941
	sleep(4);
942

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

    
946
	/* wait for flushing to finish */
947
	sleep(1);
948

    
949
	/* if ipsec is enabled, start up again */
950
	if (isset($ipseccfg['enable'])) {
951
		log_error("Forcefully reloading IPsec racoon daemon");
952
		vpn_ipsec_configure();
953
	}
954

    
955
}
956

    
957
/* master setup for vpn (mpd) */
958
function vpn_setup() {
959
	/* start pptpd */
960
	vpn_pptpd_configure();
961

    
962
	/* start pppoe server */
963
	vpn_pppoe_configure();
964

    
965
	/* setup l2tp */
966
	vpn_l2tp_configure();
967
}
968

    
969
function vpn_pptpd_configure() {
970
	global $config, $g;
971

    
972
	$syscfg = $config['system'];
973
	$pptpdcfg = $config['pptpd'];
974

    
975
	if ($g['booting']) {
976
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
977
			return 0;
978

    
979
		echo "Configuring PPTP VPN service... ";
980
	} else {
981
		/* kill mpd */
982
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
983

    
984
		/* wait for process to die */
985
		sleep(3);
986

    
987
		if (is_process_running("mpd -b")) {
988
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
989
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
990
		}
991

    
992
		/* remove mpd.conf, if it exists */
993
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
994
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
995
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
996
	}
997

    
998
	/* make sure pptp-vpn directory exists */
999
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1000
		mkdir("{$g['varetc_path']}/pptp-vpn");
1001

    
1002
	switch ($pptpdcfg['mode']) {
1003
		case 'server' :
1004
			/* write mpd.conf */
1005
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1006
			if (!$fd) {
1007
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
1008
				return 1;
1009
			}
1010

    
1011
			$mpdconf = <<<EOD
1012
pptpd:
1013

    
1014
EOD;
1015

    
1016
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1017
				$mpdconf .= "	load pt{$i}\n";
1018
			}
1019

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

    
1022
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1023

    
1024
				$mpdconf .= <<<EOD
1025

    
1026
pt{$i}:
1027
	new -i pptpd{$i} pt{$i} pt{$i}
1028
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1029
	load pts
1030

    
1031
EOD;
1032
			}
1033

    
1034
			$mpdconf .=<<<EOD
1035

    
1036
pts:
1037
	set iface disable on-demand
1038
	set iface enable proxy-arp
1039
	set iface enable tcpmssfix
1040
	set iface idle 1800
1041
	set iface up-script /usr/local/sbin/pptp-linkup
1042
	set iface down-script /usr/local/sbin/vpn-linkdown
1043
	set bundle enable multilink
1044
	set bundle enable crypt-reqd
1045
	set link yes acfcomp protocomp
1046
	set link no pap chap
1047
	set link enable chap-msv2
1048
	set link mtu 1460
1049
	set link keep-alive 10 60
1050
	set ipcp yes vjcomp
1051
	set bundle enable compression
1052
	set ccp yes mppc
1053
	set ccp yes mpp-e128
1054
	set ccp yes mpp-stateless
1055

    
1056
EOD;
1057

    
1058
			if (!isset ($pptpdcfg['req128'])) {
1059
				$mpdconf .=<<<EOD
1060
	set ccp yes mpp-e40
1061
	set ccp yes mpp-e56
1062

    
1063
EOD;
1064
			}
1065

    
1066
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
1067
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
1068
			if (is_array($pptpdcfg['dnsserver']) && ($pptpdcfg['dnsserver'][0])) {
1069
				$mpdconf .= "	set ipcp dns " . join(" ", $pptpdcfg['dnsserver']) . "\n";
1070
			} else
1071
				if (isset ($config['dnsmasq']['enable'])) {
1072
					$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1073
					if ($syscfg['dnsserver'][0])
1074
						$mpdconf .= " " . $syscfg['dnsserver'][0];
1075
					$mpdconf .= "\n";
1076
				} else
1077
					if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1078
						$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1079
					}
1080

    
1081
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1082
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1083
				$acctport = $authport + 1;
1084
				$mpdconf .=<<<EOD
1085
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1086

    
1087
EOD;
1088
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1089
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1090
				$acctport = $authport + 1;
1091
				$mpdconf .=<<<EOD
1092
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1093

    
1094
EOD;
1095
			}
1096
			$mpdconf .=<<<EOD
1097
	set radius retries 3
1098
	set radius timeout 10
1099
	set auth enable radius-auth
1100

    
1101
EOD;
1102

    
1103
				if (isset ($pptpdcfg['radius']['accounting'])) {
1104
					$mpdconf .=<<<EOD
1105
	set auth enable radius-acct
1106
	set radius acct-update 300
1107

    
1108
EOD;
1109
				}
1110
			}
1111

    
1112
			fwrite($fd, $mpdconf);
1113
			fclose($fd);
1114

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

    
1122
			$mpdlinks = "";
1123

    
1124
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1125
				$mpdlinks .=<<<EOD
1126

    
1127
pt{$i}:
1128
	set link type pptp
1129
	set pptp enable incoming
1130
	set pptp disable originate
1131
	set pptp disable windowing
1132

    
1133
EOD;
1134
			}
1135

    
1136
			fwrite($fd, $mpdlinks);
1137
			fclose($fd);
1138

    
1139
			/* write mpd.secret */
1140
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1141
			if (!$fd) {
1142
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
1143
				return 1;
1144
			}
1145

    
1146
			$mpdsecret = "";
1147

    
1148
			if (is_array($pptpdcfg['user'])) {
1149
				foreach ($pptpdcfg['user'] as $user)
1150
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1151
			}
1152

    
1153
			fwrite($fd, $mpdsecret);
1154
			fclose($fd);
1155
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1156

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

    
1160
			break;
1161

    
1162
		case 'redir' :
1163
			break;
1164
	}
1165

    
1166
	if ($g['booting'])
1167
		echo "done\n";
1168

    
1169
	return 0;
1170
}
1171

    
1172
function vpn_pppoe_configure() {
1173
	global $config, $g;
1174

    
1175
	$syscfg = $config['system'];
1176
	$pppoecfg = $config['pppoe'];
1177

    
1178
	/* create directory if it does not exist */
1179
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1180
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1181

    
1182
	if ($g['booting']) {
1183
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1184
			return 0;
1185

    
1186
		echo "Configuring PPPoE VPN service... ";
1187
	} else {
1188
		/* kill mpd */
1189
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1190

    
1191
		/* wait for process to die */
1192
		sleep(2);
1193

    
1194
	}
1195

    
1196
	/* make sure pppoe-vpn directory exists */
1197
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1198
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1199

    
1200
	switch ($pppoecfg['mode']) {
1201

    
1202
		case 'server' :
1203

    
1204
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1205

    
1206
			if ($pppoecfg['paporchap'] == "chap")
1207
				$paporchap = "set link enable chap";
1208
			else
1209
				$paporchap = "set link enable pap";
1210

    
1211
			/* write mpd.conf */
1212
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.conf", "w");
1213
			if (!$fd) {
1214
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1215
				return 1;
1216
			}
1217
			$mpdconf = "\n\n";
1218
			$mpdconf .=<<<EOD
1219
pppoe:
1220

    
1221
EOD;
1222

    
1223
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1224
				$mpdconf .= "	load pppoe{$i}\n";
1225
			}
1226

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

    
1229
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1230

    
1231
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1232
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1233
				} else {
1234
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1235
				}
1236

    
1237
				$mpdconf .=<<<EOD
1238

    
1239
pppoe{$i}:
1240
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1241
	{$isssue_ip_type}
1242
	load pppoe_standart
1243

    
1244
EOD;
1245
			}
1246

    
1247
			$mpdconf .=<<<EOD
1248

    
1249
pppoe_standart:
1250
	set bundle no multilink
1251
	set bundle enable compression
1252
	set auth max-logins 1
1253
	set iface up-script /usr/local/sbin/pppoe-linkup
1254
        set iface down-script /usr/local/sbin/vpn-linkdown
1255
	set iface idle 0
1256
	set iface disable on-demand
1257
	set iface disable proxy-arp
1258
	set iface enable tcpmssfix
1259
	set iface mtu 1500
1260
	set link no pap chap
1261
	{$paporchap}
1262
	set link keep-alive 60 180
1263
	set ipcp yes vjcomp
1264
	set ipcp no vjcomp
1265
	set link max-redial -1
1266
	set link mtu 1492
1267
	set link mru 1492
1268
	set ccp yes mpp-e40
1269
	set ccp yes mpp-e128
1270
	set ccp yes mpp-stateless
1271
	set link latency 1
1272
	#set ipcp dns 10.10.1.3
1273
	#set bundle accept encryption
1274

    
1275
EOD;
1276

    
1277
			if (isset ($config['dnsmasq']['enable'])) {
1278
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1279
				if ($syscfg['dnsserver'][0])
1280
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1281
				$mpdconf .= "\n";
1282
			} else
1283
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1284
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1285
				}
1286

    
1287
			if (isset ($pppoecfg['radius']['enable'])) {
1288
				$mpdconf .=<<<EOD
1289
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
1290
	set radius retries 3
1291
	set radius timeout 10
1292
	set auth enable radius-auth
1293

    
1294
EOD;
1295

    
1296
				if (isset ($pppoecfg['radius']['accounting'])) {
1297
					$mpdconf .=<<<EOD
1298
	set auth enable radius-acct
1299

    
1300
EOD;
1301
				}
1302
			}
1303

    
1304
			fwrite($fd, $mpdconf);
1305
			fclose($fd);
1306

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

    
1314
			$mpdlinks = "";
1315

    
1316
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1317
				$mpdlinks .=<<<EOD
1318
			
1319
pppoe{$i}:
1320
	set phys type pppoe
1321
        set pppoe iface {$pppoe_interface}
1322
        set pppoe service "*"
1323
        set pppoe disable originate
1324
        set pppoe enable incoming
1325

    
1326
EOD;
1327
			}
1328

    
1329
			fwrite($fd, $mpdlinks);
1330
			fclose($fd);
1331

    
1332
			/* write mpd.secret */
1333
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.secret", "w");
1334
			if (!$fd) {
1335
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1336
				return 1;
1337
			}
1338

    
1339
			$mpdsecret = "\n\n";
1340

    
1341
			if (is_array($pppoecfg['user'])) {
1342
				foreach ($pppoecfg['user'] as $user)
1343
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1344
			}
1345

    
1346
			fwrite($fd, $mpdsecret);
1347
			fclose($fd);
1348
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1349

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

    
1353
			break;
1354

    
1355
		case 'redir' :
1356
			break;
1357
	}
1358

    
1359
	if ($g['booting'])
1360
		echo "done\n";
1361

    
1362
	return 0;
1363
}
1364

    
1365
function vpn_l2tp_configure() {
1366
	global $config, $g;
1367

    
1368
	$syscfg = $config['system'];
1369
	$l2tpcfg = $config['l2tp'];
1370

    
1371
	/* create directory if it does not exist */
1372
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1373
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1374

    
1375
	if ($g['booting']) {
1376
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1377
			return 0;
1378

    
1379
		echo "Configuring l2tp VPN service... ";
1380
	} else {
1381
		/* kill mpd */
1382
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1383

    
1384
		/* wait for process to die */
1385
		sleep(8);
1386

    
1387
	}
1388

    
1389
	/* make sure l2tp-vpn directory exists */
1390
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1391
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1392

    
1393
	switch ($l2tpcfg['mode']) {
1394

    
1395
		case 'server' :
1396
			if ($l2tpcfg['paporchap'] == "chap")
1397
				$paporchap = "set link enable chap";
1398
			else
1399
				$paporchap = "set link enable pap";
1400

    
1401
			/* write mpd.conf */
1402
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1403
			if (!$fd) {
1404
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1405
				return 1;
1406
			}
1407
			$mpdconf = "\n\n";
1408
			$mpdconf .=<<<EOD
1409
l2tp:
1410

    
1411
EOD;
1412

    
1413
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1414
				$mpdconf .= "	load l2tp{$i}\n";
1415
			}
1416

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

    
1419
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1420

    
1421
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1422
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1423
				} else {
1424
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1425
				}
1426

    
1427
				$mpdconf .=<<<EOD
1428

    
1429
l2tp{$i}:
1430
	new l2tp{$i} l2tp{$i}
1431
	{$isssue_ip_type}
1432
	load l2tp_standard
1433

    
1434
EOD;
1435
			}
1436

    
1437
			$mpdconf .=<<<EOD
1438

    
1439
l2tp_standard:
1440
        set bundle disable multilink
1441
        set bundle enable compression
1442
        set bundle yes crypt-reqd
1443
        set ipcp yes vjcomp
1444
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1445
        set ccp yes mppc
1446
        set iface disable on-demand
1447
        set iface enable proxy-arp
1448
	set iface up-script /usr/local/sbin/l2tp-linkup
1449
        set iface down-script /usr/local/sbin/vpn-linkdown
1450
        set link yes acfcomp protocomp
1451
        set link no pap chap
1452
        set link enable chap
1453
        set link keep-alive 10 180
1454

    
1455
EOD;
1456

    
1457
			if (isset ($config['dnsmasq']['enable'])) {
1458
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1459
				if ($syscfg['dnsserver'][0])
1460
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1461
				$mpdconf .= "\n";
1462
			} else
1463
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1464
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1465
				}
1466

    
1467
			if (isset ($l2tpcfg['radius']['enable'])) {
1468
				$mpdconf .=<<<EOD
1469
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1470
	set radius retries 3
1471
	set radius timeout 10
1472
	set auth enable radius-auth
1473

    
1474
EOD;
1475

    
1476
				if (isset ($l2tpcfg['radius']['accounting'])) {
1477
					$mpdconf .=<<<EOD
1478
	set auth enable radius-acct
1479

    
1480
EOD;
1481
				}
1482
			}
1483

    
1484
			fwrite($fd, $mpdconf);
1485
			fclose($fd);
1486

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

    
1494
			$mpdlinks = "";
1495

    
1496
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1497
				$mpdlinks .=<<<EOD
1498

    
1499
l2tp{$i}:
1500
	set link type l2tp
1501
        set l2tp enable incoming
1502
        set l2tp disable originate
1503

    
1504
EOD;
1505
			if (!empty($l2tpcfg['secret']))
1506
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1507
			}
1508

    
1509
			fwrite($fd, $mpdlinks);
1510
			fclose($fd);
1511

    
1512
			/* write mpd.secret */
1513
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1514
			if (!$fd) {
1515
				printf("Error: cannot open mpd.secret in vpn_l2tp_configure().\n");
1516
				return 1;
1517
			}
1518

    
1519
			$mpdsecret = "\n\n";
1520

    
1521
			if (is_array($l2tpcfg['user'])) {
1522
				foreach ($l2tpcfg['user'] as $user)
1523
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1524
			}
1525

    
1526
			fwrite($fd, $mpdsecret);
1527
			fclose($fd);
1528
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1529

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

    
1533
			break;
1534

    
1535
		case 'redir' :
1536
			break;
1537
	}
1538

    
1539
	if ($g['booting'])
1540
		echo "done\n";
1541

    
1542
	return 0;
1543
}
1544

    
1545
/* Walk the tunnels for hostname endpoints. If the hostnames 
1546
 * resolve to a different IP now compared to the DNS cache
1547
 * we reload the policies if the endpoint has changed */
1548
function vpn_ipsec_refresh_policies() {
1549
	global $config;
1550
	global $g;
1551

    
1552
	$ipseccfg = $config['ipsec'];
1553
	$a_phase1 = $config['ipsec']['phase1'];
1554
	$a_phase2 = $config['ipsec']['phase2'];
1555

    
1556
	if (isset($ipseccfg['disable'])) {
1557
		return true;
1558
	}
1559

    
1560
	/* Walk the Ipsec tunnel array */
1561
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1562
		return;
1563
	}
1564

    
1565
	foreach ($a_phase1 as $phase1) {
1566
		if (isset($phase1['disabled'])) {
1567
			continue;
1568
		}
1569
		if (is_ipaddr($phase1['remote-gateway'])) {
1570
			continue;
1571
		}
1572
		if (!is_ipaddr($phase1['remote-gateway'])) {
1573
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1574
			$dnscache = trim($dnscache);
1575
			/* we should have the old IP addresses in the dnscache now */
1576
			if($dnscache <> "") {
1577
				$oldphase1 = $phase1;
1578
				$oldphase1['remote-gateway'] = trim($dnscache);
1579
				/* now we need to find all tunnels for this host */
1580
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1581
					continue;
1582
				}
1583
				foreach ($a_phase2 as $phase2) {
1584
					if($phase2['ikeid'] == $phase1['ikeid']) {
1585
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1586
					}
1587
				}
1588
			}
1589
		}
1590
	}
1591

    
1592
	/* process all generated spd.conf files from tmp which are left behind
1593
	 * behind by either changes of dynamic tunnels or manual edits
1594
	 * scandir() is only available in PHP5 */
1595
	$tmpfiles = array();
1596
	$dh  = opendir($g['tmp_path']);
1597
	while (false !== ($filename = readdir($dh))) {
1598
		if(preg_match("/^spd.conf.reload./", $filename)) {
1599
			$tmpfiles[] = $filename;
1600
		}
1601
	}
1602
	sort($tmpfiles);
1603
	foreach($tmpfiles as $tmpfile) {
1604
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1605
		if($ret == 0) {
1606
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1607
		} else {
1608
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1609
		}
1610
	}
1611
}
1612

    
1613
/* reloads the tunnel configuration for a tunnel item
1614
 * Will remove and add SPD polices */
1615
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1616
	global $config;
1617
	global $g;
1618

    
1619
	/* if we are not passed a old tunnel array we create one */
1620
	if(empty($old_phase1)) {
1621
		$old_phase1 = $phase1;
1622
	}
1623
	if(empty($old_phase2)) {
1624
		$old_phase2 = $phase2;
1625
	}
1626

    
1627
	$sad_arr = ipsec_dump_sad();
1628

    
1629
	$ep = ipsec_get_phase1_src($phase1);
1630
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1631
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1632

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

    
1636
	$old_ep = ipsec_get_phase1_src($old_phase1);
1637
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1638
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1639

    
1640
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1641
	 * try to resolve it now and add it to the list for dnswatch */
1642
	if (!is_ipaddr($phase1['remote-gateway'])) {
1643
		$rgip = resolve_retry($phase1['remote-gateway']);
1644
		add_hostname_to_watch($phase1['remote-gateway']);
1645
		if (!$rgip) {
1646
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1647
			return false;
1648
		}
1649
	} else {
1650
		$rgip = $phase1['remote-gateway'];
1651
	}
1652
	if (!$ep) {
1653
		log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1654
		return false;
1655
	}
1656

    
1657
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1658
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1659
	}
1660
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1661
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1662
	}
1663

    
1664
	$spdconf = "";
1665
	/* Delete old SPD policies if there are changes between the old and new */
1666
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1667
		$spdconf .= "spddelete {$old_local_subnet} " .
1668
			"{$old_remote_subnet} any -P out ipsec " .
1669
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1670
			"{$old_gw}/unique;\n";
1671
		$spdconf .= "spddelete {$old_remote_subnet} " .
1672
			"{$old_local_subnet} any -P in ipsec " .
1673
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1674
			"{$old_ep}/unique;\n";
1675

    
1676
		/* zap any existing SA entries */
1677
		foreach($sad_arr as $sad) {
1678
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1679
				$spdconf .= "delete {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1680
			}
1681
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1682
				$spdconf .= "delete {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1683
			}
1684
		}
1685
	}
1686

    
1687
	/* Create new SPD entries for the new configuration */
1688
	/* zap any existing SA entries beforehand */
1689
	foreach($sad_arr as $sad) {
1690
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1691
			$spdconf .= "delete {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1692
		}
1693
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1694
			$spdconf .= "delete {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1695
		}
1696
	}
1697
	/* add new SPD policies to replace them */
1698
	$spdconf .= "spdadd {$local_subnet} " .
1699
		"{$remote_subnet} any -P out ipsec " .
1700
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1701
		"{$rgip}/unique;\n";
1702
	$spdconf .= "spdadd {$remote_subnet} " .
1703
		"{$local_subnet} any -P in ipsec " .
1704
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1705
		"{$ep}/unique;\n";
1706

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

    
1709
	$now = time();
1710
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1711
	/* generate temporary spd.conf */
1712
	file_put_contents($spdfile, $spdconf);
1713
	return true;
1714
}
1715

    
1716
?>
(44-44/50)