Project

General

Profile

Download (46.5 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 vpn_ipsec_configure($ipchg = false)
82
{
83
	global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos;
84

    
85
	/* get the automatic ping_hosts.sh ready */
86
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
87
	touch("{$g['vardb_path']}/ipsecpinghosts");
88

    
89
	if(isset($config['ipsec']['preferoldsa']))
90
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
91
	else
92
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
93

    
94
	$syscfg = $config['system'];
95
	$ipseccfg = $config['ipsec'];
96
	$a_phase1 = $config['ipsec']['phase1'];
97
	$a_phase2 = $config['ipsec']['phase2'];
98
	$a_client = $config['ipsec']['client'];
99

    
100
	if (!isset($ipseccfg['enable'])) {
101
		mwexec("/sbin/ifconfig enc0 down");
102

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

    
106
		/* kill racoon */
107
		if(is_process_running("racoon"))
108
			mwexec("/usr/bin/killall racoon", true);
109
		killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
110

    
111
		/* wait for racoon process to die */
112
		sleep(2);
113

    
114
		/* flush SPD and SAD */
115
		mwexec("/usr/local/sbin/setkey -F");
116
		mwexec("/usr/local/sbin/setkey -FP");
117

    
118
		/* disallow IPSEC, it is off */
119
//		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
120

    
121
		return true;
122
	} else {
123
		mwexec("/sbin/ifconfig enc0 up");
124

    
125
		if ($g['booting'])
126
			echo "Configuring IPsec VPN... ";
127

    
128
		/* fastforwarding is not compatible with ipsec tunnels */
129
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
130

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

    
135
		/* resolve all local, peer addresses and setup pings */
136
		$ipmap = array();
137
		$rgmap = array();
138
		$dnswatch_list = array();
139
		if (is_array($a_phase1) && count($a_phase1)) {
140

    
141
			/* step through each phase1 entry */
142
			foreach ($a_phase1 as $ph1ent) {
143
				if (isset($ph1ent['disabled']))
144
					continue;
145

    
146
				$ep = ipsec_get_phase1_src($ph1ent);
147
				if (!$ep)
148
					continue;
149

    
150
				if(!in_array($ep,$ipmap))
151
					$ipmap[] = $ep;
152

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

    
156
				if (isset ($ph1ent['mobile']))
157
					continue;
158

    
159
				$rg = $ph1ent['remote-gateway'];
160

    
161
				if (!is_ipaddr($rg)) {
162
					$dnswatch_list[] = "{$rg} = value";
163
					add_hostname_to_watch($rg);
164
					$rg = resolve_retry($rg);
165
					if (!$rg)
166
						continue;
167
				}
168

    
169
				$rgmap[$ph1ent['remote-gateway']] = $rg;
170

    
171
				/* step through each phase2 entry */
172
				$ipsecpinghosts = "";
173
				foreach ($a_phase2 as $ph2ent) {
174

    
175
					$ikeid = $ph2ent['ikeid'];
176

    
177
					if (isset($ph2ent['disabled']))
178
						continue;
179

    
180
					if ($ikeid != $ph1ent['ikeid'])
181
						continue;
182

    
183
					/* add an ipsec pinghosts entry */
184
					if ($ph2ent['pinghost']) {
185
						$iflist = get_configured_interface_list();
186
						foreach ($iflist as $ifent => $ifname) {
187
							$interface_ip = get_interface_ip($ifent);
188
							$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
189
							if (ip_in_subnet($interface_ip, $local_subnet)) {
190
								$srcip = $interface_ip;
191
								break;
192
							}
193
						}
194
						$dstip = $ph2ent['pinghost'];
195
						if (is_ipaddr($srcip))
196
							$ipsecpinghosts .= "{$srcip}|{$dstip}|3\n";
197
					}
198
				}
199
				$pfd = fopen("{$g['vardb_path']}/ipsecpinghosts", "w");
200
				if ($pfd) {
201
					fwrite($pfd, $ipsecpinghosts);
202
					fclose($pfd);
203
				}
204
				
205
			}
206
		}
207

    
208
		/* generate CA certificates files */
209
		if (is_array($config['system']['ca']) && count($config['system']['ca'])) {
210
			foreach ($config['system']['ca'] as $ca) {
211
				if (!isset($ca['crt'])) {
212
					log_error("Error: Invalid certificate info for {$ca['name']}");
213
					continue;
214
				}
215
				$cert = base64_decode($ca['crt']);
216
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
217
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
218
					log_error("Error: Invalid certificate hash info for {$ca['name']}");
219
					continue;
220
				}
221
				$fname = $g['varetc_path']."/".$x509cert['hash'].".0";
222
				if (!file_put_contents($fname, $cert)) {
223
					log_error("Error: Cannot write IPsec CA file for {$ca['name']}");
224
					continue;
225
				}
226
			}
227
		}
228
		
229
		/* generate psk.txt */
230
		$fd = fopen("{$g['varetc_path']}/psk.txt", "w");
231
		if (!$fd) {
232
			printf("Error: cannot open psk.txt in vpn_ipsec_configure().\n");
233
			return 1;
234
		}
235

    
236
		$pskconf = "";
237

    
238
		if (is_array($a_phase1) && count($a_phase1)) {
239
			foreach ($a_phase1 as $ph1ent) {
240

    
241
				if (isset($ph1ent['disabled']))
242
					continue;
243

    
244
				if (strstr($ph1ent['authentication_method'],'rsa'))
245
					continue;
246

    
247
				$peerid_type = $ph1ent['peerid_type'];
248

    
249
				switch ($peerid_type) {
250
					case "peeraddress":
251
						$peerid_type = "address";
252
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
253
						break;
254

    
255
					case "address";
256
						$peerid_data = $ph1ent['peerid_data'];
257
						break;
258

    
259
					case "fqdn";
260
					case "keyid tag";
261
					case "user_fqdn";
262
						$peerid_data = $ph1ent['peerid_data'];
263
						break;
264
				}
265

    
266
				$pskconf .= "{$peerid_data}\t{$ph1ent['pre-shared-key']}\n";
267
			}
268
		}
269

    
270
		/* Add user PSKs */
271
		foreach ($config['system']['user'] as $user) {
272
			if (!empty($user['ipsecpsk'])) {
273
				$pskconf .= "{$user['name']}\t{$user['ipsecpsk']}\n";
274
			}
275
		}
276

    
277
		/* add PSKs for mobile clients */
278
		if (is_array($ipseccfg['mobilekey'])) {
279
			foreach ($ipseccfg['mobilekey'] as $key) {
280
				$pskconf .= "{$key['ident']}\t{$key['pre-shared-key']}\n";
281
			}
282
		}
283

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

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

    
298
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
299
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
300
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
301

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

    
314
			/* begin mode_cfg section */
315
			if (is_array($a_client) && isset($a_client['enable'])) {
316

    
317
				$racoonconf .= "\nmode_cfg\n";
318
				$racoonconf .= "{\n";
319

    
320
				if ($a_client['user_source'])
321
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
322
				if ($a_client['group_source'])
323
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
324

    
325
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
326
					$pool_address = $a_client['pool_address'];
327
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
328

    
329
					$pool_address = long2ip32(ip2long($pool_address)+1);
330
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
331

    
332
					$racoonconf .= "\tpool_size {$pool_size};\n";
333
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
334
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
335
				}
336

    
337
				if (isset($a_client['net_list'])) {
338

    
339
					$net_list = '';
340

    
341
					foreach ($a_phase2 as $ph2ent) {
342

    
343
						if (isset($ph2ent['disabled']))
344
							continue;
345

    
346
						if (!isset($ph2ent['mobile']))
347
							continue;
348

    
349
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
350

    
351
						if ($net_list)
352
							$net_list .= ", ";
353
						$net_list .= $localid;
354
					}
355

    
356
					if ($net_list)
357
						$racoonconf .= "\tsplit_network include {$net_list};\n";
358
				}
359

    
360
				if ($a_client['dns_server1'])
361
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
362
				if ($a_client['dns_server2'])
363
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
364
				if ($a_client['dns_server3'])
365
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
366
				if ($a_client['dns_server4'])
367
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
368

    
369
				if ($a_client['wins_server1'])
370
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
371
				if ($a_client['wins_server2'])
372
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
373

    
374
				if ($a_client['dns_domain']) {
375
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
376
					$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
377
				}
378

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

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

    
390
					fwrite($fd1, $a_client['login_banner']);
391
					fclose($fd1);
392

    
393
					$racoonconf .= "\tbanner \"{$fn}\";\n";
394
				}
395

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

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

    
405
					if (isset($ph1ent['disabled']))
406
						continue;
407

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

    
411
					$ikeid = $ph1ent['ikeid'];
412

    
413
					$ep = ipsec_get_phase1_src($ph1ent);
414
					if (!$ep)
415
						continue;
416

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

    
423
					$myid_type = $ph1ent['myid_type'];
424

    
425
					switch ($myid_type) {
426

    
427
						case "myaddress":
428
							$myid_type = "address";
429
							$myid_data = $ep;
430
							break;
431

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

    
437
						case "address";
438
							$myid_data = $ph1ent['myid_data'];
439
							break;
440

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

    
451
					$peerid_type = $ph1ent['peerid_type'];
452

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

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

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

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

    
477
					$init = "on";
478
					$genp = "off";
479
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
480
					$passive = "";
481
					if (isset($ph1ent['mobile'])) {
482
						$rgip = "anonymous";
483
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
484
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
485
							$passive = "passive on;";
486
							$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
487
							$genp = "on";
488
						} else {
489
							$init = "off";
490
							$genp = "unique";
491
						}
492
					}
493

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

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

    
506
					$certline = '';
507

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

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

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

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

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

    
527
						chmod($certpath, 0600);
528

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

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

    
538
						chmod($keypath, 0600);
539

    
540
						$ca = lookup_ca($ph1ent['caref']);
541
						if ($ca) {
542
							$cafile = "ca-".$ikeid.".crt";
543
							$capath = $g['varetc_path']."/".$cafile;
544

    
545
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
546
							{
547
								log_error("Error: Cannot write phase1 CA certificate file for {$ph1ent['name']}");
548
								continue;
549
							}
550

    
551
							chmod($capath, 0600);
552
							$caline = "ca_type x509 \"".basename($capath)."\";";
553
						}
554

    
555
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
556

    
557
					}
558

    
559
					$ealgos = '';
560
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
561
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
562
					if ($ealg_kl)
563
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
564
					else
565
						$ealgos = $ealgos.$ealg_id;
566

    
567
					$lifeline = '';
568
					if ($ph1ent['lifetime'])
569
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
570

    
571
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
572
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
573
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
574
					}
575

    
576
					/* add remote section to configuration */
577

    
578
					$racoonconf .=<<<EOD
579

    
580
remote {$rgip}
581
{
582
	ph1id {$ikeid};
583
	exchange_mode {$ph1ent['mode']};
584
	my_identifier {$myid_type} {$myid_data};
585
	{$peerid_spec}
586
	ike_frag on;
587
	generate_policy = {$genp};
588
	initial_contact = {$init};
589
	nat_traversal = {$natt};
590
	{$certline}
591
	{$caline}
592
	{$dpdline1}
593
	{$dpdline2}
594
	support_proxy on;
595
	proposal_check {$pcheck};
596
	{$passive}
597

    
598
	proposal
599
	{
600
		authentication_method {$authmethod};
601
		encryption_algorithm ${ealgos};
602
		hash_algorithm {$ph1ent['hash-algorithm']};
603
		dh_group {$ph1ent['dhgroup']};
604
		${lifeline}
605
	}
606
}
607

    
608
EOD;
609
				}
610
				/* end remote */
611
			}
612
			/* end remote sections */
613
		
614
			/* begin sainfo sections */
615
			if (is_array($a_phase2) && count($a_phase2)) {
616

    
617
				/* begin sainfo */
618
				foreach ($a_phase2 as $ph2ent) {
619

    
620
					$ikeid = $ph2ent['ikeid'];
621

    
622
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
623
						continue;
624

    
625
					if (isset($ph1ent['disabled']))
626
						continue;
627

    
628
					if (isset($ph2ent['disabled']))
629
						continue;
630

    
631
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
632
						continue;
633

    
634
					if ($ph2ent['mode'] == 'tunnel') {
635

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

    
646
						if (!isset($ph2ent['mobile'])) {
647
							$remoteid_type = $ph2ent['remoteid']['type'];
648
							if ($remoteid_type != "address")
649
								$remoteid_type = "subnet";
650

    
651
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
652
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
653
						} else
654
							$remoteid_spec = "anonymous";
655

    
656
					} else {
657

    
658
						$rgip = $rgmap[$ph1ent['remote-gateway']];
659

    
660
						$localid_data = ipsec_get_phase1_src($ph1ent);
661
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
662
						$localid_spec = "address {$localid_data}";
663

    
664
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
665
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
666
						$remoteid_spec = "address {$remoteid_data}";
667
					}
668

    
669
					if($ph2ent['protocol'] == 'esp') {
670

    
671
						$ealgos = '';
672

    
673
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
674

    
675
							$ealg_id = $ealg['name'];
676
							$ealg_kl = $ealg['keylen'];
677

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

    
713
						$ealgosline = "encryption_algorithm {$ealgos};";
714

    
715
					} else {
716

    
717
						$ealgosline = "encryption_algorithm null_enc;";
718
					}
719

    
720
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
721
					$halgosline = "authentication_algorithm {$halgos};";
722

    
723
					$pfsline = '';
724
					if ($ph2ent['pfsgroup'])
725
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
726
					if (isset($a_client['pfs_group'])) {
727
						$pfsline = '';
728
						if ($a_client['pfs_group'])
729
							$pfsline = "pfs_group {$a_client['pfs_group']};";
730
					}
731

    
732
					$lifeline = '';
733
					if ($ph2ent['lifetime'])
734
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
735

    
736
					/* add sainfo section to configuration */
737
					
738
					$racoonconf .=<<<EOD
739
					
740
sainfo {$localid_spec} {$remoteid_spec}
741
{
742
	remoteid {$ikeid};
743
	{$ealgosline}
744
	{$halgosline}
745
	{$pfsline}
746
	{$lifeline}
747
	compression_algorithm deflate;
748
}
749

    
750
EOD;
751
				}
752
				/* end sainfo */
753
			}
754
			/* end sainfo sections */
755

    
756
			fwrite($fd, $racoonconf);
757
			fclose($fd);
758
		}
759
		/* end racoon.conf */
760

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

    
770
			$spdconf = "";
771

    
772
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
773
			if ($config['interfaces']['lan']) {
774
				$lanip = get_interface_ip("lan");
775
				if (!empty($lanip) && is_ipaddr($lanip)) {
776
					$lansn = get_interface_subnet("lan");
777
					$lansa = gen_subnet($lanip, $lansn);
778
					$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
779
					$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
780
				}
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($ph2ent['mode'] == "tunnel") {
807

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

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

    
814
				} else {
815

    
816
					$localid_data = ipsec_get_phase1_src($ph1ent);
817
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
818

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

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

    
825
				}
826

    
827
				/* static route needed? */
828
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
829
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
830
				else
831
					$parentinterface = $ph1ent['interface'];
832

    
833
				if ($parentinterface <> "wan") {
834
					/* add endpoint routes to correct gateway on interface */
835
					if (interface_has_gateway($parentinterface)) {
836
						$gatewayip = get_interface_gateway("$parentinterface");
837
						$interfaceip = get_interface_ip($parentinterface);
838
						$subnet_bits = get_interface_subnet($parentinterface);
839
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
840
						/* if the remote gateway is in the local subnet, then don't add a route */
841
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
842
							if(is_ipaddr($gatewayip)) {
843
								/* FIXME: does adding route-to and reply-to on the in/outbound
844
								 * rules fix this? smos@ 13-01-2009 */
845
								log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
846
								mwexec("/sbin/route delete -host {$rgip}");
847
								mwexec("/sbin/route add -host {$rgip} {$gatewayip}");
848
							}
849
						}
850
					}
851
				} else {
852
					if(stristr($route_str, "{$rgip}")) {
853
						mwexec("/sbin/route delete -host {$rgip}", true);
854
					}
855
				}
856
			}
857

    
858
			fwrite($fd, $spdconf);
859
			fclose($fd);
860
		}
861

    
862
		/* needed for racoonctl admin socket */
863
		if (!is_dir("/var/db/racoon"))
864
			mkdir("/var/db/racoon/");
865
		
866
		/* mange racoon process */
867
		if (is_process_running("racoon")) {
868
			sleep("0.1");
869
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
870
			/* load SPD without flushing to be safe on config additions or changes. */
871
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
872
		} else {
873
			/* flush SA + SPD entries */
874
			mwexec("/usr/local/sbin/setkey -FP", false);
875
 			sleep("0.1");
876
			mwexec("/usr/local/sbin/setkey -F", false);
877
 			sleep("0.1");
878
//			exec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
879
 			/* start racoon */
880
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
881
 			sleep("0.1");
882
 			/* load SPD */
883
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
884

    
885
			/* start dnswatch, if necessary */
886
			if (count($dnswatch_list) > 0) {
887
				$interval = 60;
888
				if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
889
					$interval = $ipseccfg['dns-interval'];
890

    
891
				$hostnames = "";
892
				array_unique($dnswatch_list);
893
				$hostnames = implode("\n", $dnswatch_list);
894
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
895

    
896
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
897
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
898
			}
899
		}
900
	
901
		vpn_ipsec_failover_configure();
902

    
903
		if ($g['booting'])
904
			echo "done\n";
905
	}
906

    
907
	return 0;
908
}
909

    
910
/* Forcefully restart IPsec
911
 * This is required for when dynamic interfaces reload
912
 * For all other occasions the normal vpn_ipsec_configure()
913
 * will gracefully reload the settings without restarting
914
 */
915
function vpn_ipsec_force_reload() {
916
	global $config;
917
	global $g;
918

    
919
	$ipseccfg = $config['ipsec'];
920

    
921
	/* kill racoon */
922
	if(is_process_running("racoon"))
923
		mwexec("/usr/bin/killall racoon", true);
924

    
925
	/* wait for process to die */
926
	sleep(4);
927

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

    
931
	/* wait for flushing to finish */
932
	sleep(1);
933

    
934
	/* if ipsec is enabled, start up again */
935
	if (isset($ipseccfg['enable'])) {
936
		log_error("Forcefully reloading IPsec racoon daemon");
937
		vpn_ipsec_configure();
938
	}
939

    
940
}
941

    
942
/* master setup for vpn (mpd) */
943
function vpn_setup() {
944
	/* start pptpd */
945
	vpn_pptpd_configure();
946

    
947
	/* start pppoe server */
948
	vpn_pppoe_configure();
949

    
950
	/* setup l2tp */
951
	vpn_l2tp_configure();
952
}
953

    
954
function vpn_pptpd_configure() {
955
	global $config, $g;
956

    
957
	$syscfg = $config['system'];
958
	$pptpdcfg = $config['pptpd'];
959

    
960
	if ($g['booting']) {
961
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
962
			return 0;
963

    
964
		echo "Configuring PPTP VPN service... ";
965
	} else {
966
		/* kill mpd */
967
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
968

    
969
		/* wait for process to die */
970
		sleep(3);
971

    
972
		if (is_process_running("mpd -b")) {
973
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
974
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
975
		}
976

    
977
		/* remove mpd.conf, if it exists */
978
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
979
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
980
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
981
	}
982

    
983
	/* make sure pptp-vpn directory exists */
984
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
985
		mkdir("{$g['varetc_path']}/pptp-vpn");
986

    
987
	switch ($pptpdcfg['mode']) {
988
		case 'server' :
989
			/* write mpd.conf */
990
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
991
			if (!$fd) {
992
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
993
				return 1;
994
			}
995

    
996
			$mpdconf = <<<EOD
997
pptpd:
998

    
999
EOD;
1000

    
1001
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1002
				$mpdconf .= "	load pt{$i}\n";
1003
			}
1004

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

    
1007
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1008

    
1009
				$mpdconf .= <<<EOD
1010

    
1011
pt{$i}:
1012
	new -i pptpd{$i} pt{$i} pt{$i}
1013
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1014
	load pts
1015

    
1016
EOD;
1017
			}
1018

    
1019
			$mpdconf .=<<<EOD
1020

    
1021
pts:
1022
	set iface disable on-demand
1023
	set iface enable proxy-arp
1024
	set iface enable tcpmssfix
1025
	set iface idle 1800
1026
	set iface up-script /usr/local/sbin/pptp-linkup
1027
	set iface down-script /usr/local/sbin/vpn-linkdown
1028
	set bundle enable multilink
1029
	set bundle enable crypt-reqd
1030
	set link yes acfcomp protocomp
1031
	set link no pap chap
1032
	set link enable chap-msv2
1033
	set link mtu 1460
1034
	set link keep-alive 10 60
1035
	set ipcp yes vjcomp
1036
	set bundle enable compression
1037
	set ccp yes mppc
1038
	set ccp yes mpp-e128
1039
	set ccp yes mpp-stateless
1040

    
1041
EOD;
1042

    
1043
			if (!isset ($pptpdcfg['req128'])) {
1044
				$mpdconf .=<<<EOD
1045
	set ccp yes mpp-e40
1046
	set ccp yes mpp-e56
1047

    
1048
EOD;
1049
			}
1050

    
1051
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
1052
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
1053

    
1054
			if (!empty($pptpdcfg['dns1'])) {
1055
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1056
				if (!empty($pptpdcfg['dns2']))
1057
					$mpdconf .= " " . $pptpdcfg['dns2'];
1058
				$mpdconf .= "\n";
1059
			} elseif (isset ($config['dnsmasq']['enable'])) {
1060
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1061
				if ($syscfg['dnsserver'][0])
1062
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1063
				$mpdconf .= "\n";
1064
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1065
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1066
			}
1067

    
1068
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1069
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1070
				$acctport = $authport + 1;
1071
				$mpdconf .=<<<EOD
1072
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1073

    
1074
EOD;
1075
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1076
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1077
				$acctport = $authport + 1;
1078
				$mpdconf .=<<<EOD
1079
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1080

    
1081
EOD;
1082
			}
1083
			$mpdconf .=<<<EOD
1084
	set radius retries 3
1085
	set radius timeout 10
1086
	set auth enable radius-auth
1087

    
1088
EOD;
1089

    
1090
				if (isset ($pptpdcfg['radius']['accounting'])) {
1091
					$mpdconf .=<<<EOD
1092
	set auth enable radius-acct
1093
	set radius acct-update 300
1094

    
1095
EOD;
1096
				}
1097
			}
1098

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

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

    
1109
			$mpdlinks = "";
1110

    
1111
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1112
				$mpdlinks .=<<<EOD
1113

    
1114
pt{$i}:
1115
	set link type pptp
1116
	set pptp enable incoming
1117
	set pptp disable originate
1118
	set pptp disable windowing
1119

    
1120
EOD;
1121
			}
1122

    
1123
			fwrite($fd, $mpdlinks);
1124
			fclose($fd);
1125

    
1126
			/* write mpd.secret */
1127
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1128
			if (!$fd) {
1129
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
1130
				return 1;
1131
			}
1132

    
1133
			$mpdsecret = "";
1134

    
1135
			if (is_array($pptpdcfg['user'])) {
1136
				foreach ($pptpdcfg['user'] as $user)
1137
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1138
			}
1139

    
1140
			fwrite($fd, $mpdsecret);
1141
			fclose($fd);
1142
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1143

    
1144
			/* fire up mpd */
1145
			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");
1146

    
1147
			break;
1148

    
1149
		case 'redir' :
1150
			break;
1151
	}
1152

    
1153
	if ($g['booting'])
1154
		echo "done\n";
1155

    
1156
	return 0;
1157
}
1158

    
1159
function vpn_pppoe_configure() {
1160
	global $config, $g;
1161

    
1162
	$syscfg = $config['system'];
1163
	$pppoecfg = $config['pppoe'];
1164

    
1165
	/* create directory if it does not exist */
1166
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1167
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1168

    
1169
	if ($g['booting']) {
1170
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1171
			return 0;
1172

    
1173
		echo "Configuring PPPoE VPN service... ";
1174
	} else {
1175
		/* kill mpd */
1176
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1177

    
1178
		/* wait for process to die */
1179
		sleep(2);
1180

    
1181
	}
1182

    
1183
	/* make sure pppoe-vpn directory exists */
1184
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1185
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1186

    
1187
	switch ($pppoecfg['mode']) {
1188

    
1189
		case 'server' :
1190

    
1191
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1192

    
1193
			if ($pppoecfg['paporchap'] == "chap")
1194
				$paporchap = "set link enable chap";
1195
			else
1196
				$paporchap = "set link enable pap";
1197

    
1198
			/* write mpd.conf */
1199
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.conf", "w");
1200
			if (!$fd) {
1201
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1202
				return 1;
1203
			}
1204
			$mpdconf = "\n\n";
1205
			$mpdconf .=<<<EOD
1206
pppoe:
1207

    
1208
EOD;
1209

    
1210
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1211
				$mpdconf .= "	load pppoe{$i}\n";
1212
			}
1213

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

    
1216
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1217

    
1218
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['server']['enable'])) {
1219
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1220
				} else {
1221
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1222
				}
1223

    
1224
				$mpdconf .=<<<EOD
1225

    
1226
pppoe{$i}:
1227
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1228
	{$isssue_ip_type}
1229
	load pppoe_standart
1230

    
1231
EOD;
1232
			}
1233

    
1234
			$mpdconf .=<<<EOD
1235

    
1236
pppoe_standart:
1237
	set bundle no multilink
1238
	set bundle enable compression
1239
	set auth max-logins 1
1240
	set iface up-script /usr/local/sbin/pppoe-linkup
1241
        set iface down-script /usr/local/sbin/vpn-linkdown
1242
	set iface idle 0
1243
	set iface disable on-demand
1244
	set iface disable proxy-arp
1245
	set iface enable tcpmssfix
1246
	set iface mtu 1500
1247
	set link no pap chap
1248
	{$paporchap}
1249
	set link keep-alive 60 180
1250
	set ipcp yes vjcomp
1251
	set ipcp no vjcomp
1252
	set link max-redial -1
1253
	set link mtu 1492
1254
	set link mru 1492
1255
	set ccp yes mpp-e40
1256
	set ccp yes mpp-e128
1257
	set ccp yes mpp-stateless
1258
	set link latency 1
1259
	#set ipcp dns 10.10.1.3
1260
	#set bundle accept encryption
1261

    
1262
EOD;
1263

    
1264
			if (!empty($pppoecfg['dns1'])) {
1265
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1266
				if (!empty($pppoecfg['dns2']))
1267
					$mpdconf .= " " . $pppoecfg['dns2'];
1268
				$mpdconf .= "\n";
1269
			} elseif (isset ($config['dnsmasq']['enable'])) {
1270
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1271
				if ($syscfg['dnsserver'][0])
1272
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1273
				$mpdconf .= "\n";
1274
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1275
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1276
			}
1277

    
1278
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1279
				$mpdconf .=<<<EOD
1280
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}"
1281
	set radius retries 3
1282
	set radius timeout 10
1283
	set auth enable radius-auth
1284

    
1285
EOD;
1286

    
1287
				if (isset ($pppoecfg['radius']['accounting'])) {
1288
					$mpdconf .=<<<EOD
1289
	set auth enable radius-acct
1290

    
1291
EOD;
1292
				}
1293
			}
1294

    
1295
			fwrite($fd, $mpdconf);
1296
			fclose($fd);
1297

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

    
1305
			$mpdlinks = "";
1306

    
1307
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1308
				$mpdlinks .=<<<EOD
1309
			
1310
pppoe{$i}:
1311
	set phys type pppoe
1312
        set pppoe iface {$pppoe_interface}
1313
        set pppoe service "*"
1314
        set pppoe disable originate
1315
        set pppoe enable incoming
1316

    
1317
EOD;
1318
			}
1319

    
1320
			fwrite($fd, $mpdlinks);
1321
			fclose($fd);
1322

    
1323
			/* write mpd.secret */
1324
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.secret", "w");
1325
			if (!$fd) {
1326
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1327
				return 1;
1328
			}
1329

    
1330
			$mpdsecret = "\n\n";
1331

    
1332
			if (is_array($pppoecfg['user'])) {
1333
				foreach ($pppoecfg['user'] as $user)
1334
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1335
			}
1336

    
1337
			fwrite($fd, $mpdsecret);
1338
			fclose($fd);
1339
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1340

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

    
1344
			break;
1345

    
1346
		case 'redir' :
1347
			break;
1348
	}
1349

    
1350
	if ($g['booting'])
1351
		echo "done\n";
1352

    
1353
	return 0;
1354
}
1355

    
1356
function vpn_l2tp_configure() {
1357
	global $config, $g;
1358

    
1359
	$syscfg = $config['system'];
1360
	$l2tpcfg = $config['l2tp'];
1361

    
1362
	/* create directory if it does not exist */
1363
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1364
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1365

    
1366
	if ($g['booting']) {
1367
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1368
			return 0;
1369

    
1370
		echo "Configuring l2tp VPN service... ";
1371
	} else {
1372
		/* kill mpd */
1373
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1374

    
1375
		/* wait for process to die */
1376
		sleep(8);
1377

    
1378
	}
1379

    
1380
	/* make sure l2tp-vpn directory exists */
1381
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1382
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1383

    
1384
	switch ($l2tpcfg['mode']) {
1385

    
1386
		case 'server' :
1387
			if ($l2tpcfg['paporchap'] == "chap")
1388
				$paporchap = "set link enable chap";
1389
			else
1390
				$paporchap = "set link enable pap";
1391

    
1392
			/* write mpd.conf */
1393
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1394
			if (!$fd) {
1395
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1396
				return 1;
1397
			}
1398
			$mpdconf = "\n\n";
1399
			$mpdconf .=<<<EOD
1400
l2tp:
1401

    
1402
EOD;
1403

    
1404
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1405
				$mpdconf .= "	load l2tp{$i}\n";
1406
			}
1407

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

    
1410
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1411

    
1412
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1413
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1414
				} else {
1415
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1416
				}
1417

    
1418
				$mpdconf .=<<<EOD
1419

    
1420
l2tp{$i}:
1421
	new l2tp{$i} l2tp{$i}
1422
	{$isssue_ip_type}
1423
	load l2tp_standard
1424

    
1425
EOD;
1426
			}
1427

    
1428
			$mpdconf .=<<<EOD
1429

    
1430
l2tp_standard:
1431
        set bundle disable multilink
1432
        set bundle enable compression
1433
        set bundle yes crypt-reqd
1434
        set ipcp yes vjcomp
1435
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1436
        set ccp yes mppc
1437
        set iface disable on-demand
1438
        set iface enable proxy-arp
1439
	set iface up-script /usr/local/sbin/l2tp-linkup
1440
        set iface down-script /usr/local/sbin/vpn-linkdown
1441
        set link yes acfcomp protocomp
1442
        set link no pap chap
1443
        set link enable chap
1444
        set link keep-alive 10 180
1445

    
1446
EOD;
1447

    
1448
			if (!empty($l2tpcfg['dns1'])) {
1449
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1450
				if (!empty($l2tpcfg['dns2']))
1451
					$mpdconf .= " " . $l2tpcfg['dns2'];
1452
				$mpdconf .= "\n";
1453
			} elseif (isset ($config['dnsmasq']['enable'])) {
1454
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1455
				if ($syscfg['dnsserver'][0])
1456
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1457
				$mpdconf .= "\n";
1458
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1459
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1460
			}
1461

    
1462
			if (isset ($l2tpcfg['radius']['enable'])) {
1463
				$mpdconf .=<<<EOD
1464
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1465
	set radius retries 3
1466
	set radius timeout 10
1467
	set auth enable radius-auth
1468

    
1469
EOD;
1470

    
1471
				if (isset ($l2tpcfg['radius']['accounting'])) {
1472
					$mpdconf .=<<<EOD
1473
	set auth enable radius-acct
1474

    
1475
EOD;
1476
				}
1477
			}
1478

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

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

    
1489
			$mpdlinks = "";
1490

    
1491
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1492
				$mpdlinks .=<<<EOD
1493

    
1494
l2tp{$i}:
1495
	set link type l2tp
1496
        set l2tp enable incoming
1497
        set l2tp disable originate
1498

    
1499
EOD;
1500
			if (!empty($l2tpcfg['secret']))
1501
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1502
			}
1503

    
1504
			fwrite($fd, $mpdlinks);
1505
			fclose($fd);
1506

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

    
1514
			$mpdsecret = "\n\n";
1515

    
1516
			if (is_array($l2tpcfg['user'])) {
1517
				foreach ($l2tpcfg['user'] as $user)
1518
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1519
			}
1520

    
1521
			fwrite($fd, $mpdsecret);
1522
			fclose($fd);
1523
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1524

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

    
1528
			break;
1529

    
1530
		case 'redir' :
1531
			break;
1532
	}
1533

    
1534
	if ($g['booting'])
1535
		echo "done\n";
1536

    
1537
	return 0;
1538
}
1539

    
1540
/* Walk the tunnels for hostname endpoints. If the hostnames 
1541
 * resolve to a different IP now compared to the DNS cache
1542
 * we reload the policies if the endpoint has changed */
1543
function vpn_ipsec_refresh_policies() {
1544
	global $config;
1545
	global $g;
1546

    
1547
	$ipseccfg = $config['ipsec'];
1548
	$a_phase1 = $config['ipsec']['phase1'];
1549
	$a_phase2 = $config['ipsec']['phase2'];
1550

    
1551
	if (isset($ipseccfg['disable'])) {
1552
		return true;
1553
	}
1554

    
1555
	/* Walk the Ipsec tunnel array */
1556
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1557
		return;
1558
	}
1559

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

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

    
1608
/* reloads the tunnel configuration for a tunnel item
1609
 * Will remove and add SPD polices */
1610
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1611
	global $config;
1612
	global $g;
1613

    
1614
	/* if we are not passed a old tunnel array we create one */
1615
	if(empty($old_phase1)) {
1616
		$old_phase1 = $phase1;
1617
	}
1618
	if(empty($old_phase2)) {
1619
		$old_phase2 = $phase2;
1620
	}
1621

    
1622
	$sad_arr = ipsec_dump_sad();
1623

    
1624
	$ep = ipsec_get_phase1_src($phase1);
1625
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1626
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1627

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

    
1631
	$old_ep = ipsec_get_phase1_src($old_phase1);
1632
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1633
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1634

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

    
1652
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1653
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1654
	}
1655
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1656
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1657
	}
1658

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

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

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

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

    
1704
	$now = time();
1705
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1706
	/* generate temporary spd.conf */
1707
	file_put_contents($spdfile, $spdconf);
1708
	return true;
1709
}
1710

    
1711
?>
(45-45/54)