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 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

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

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

    
388
					fwrite($fd1, $a_client['login_banner']);
389
					fclose($fd1);
390

    
391
					$racoonconf .= "\tbanner \"{$fn}\";\n";
392
				}
393

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

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

    
403
					if (isset($ph1ent['disabled']))
404
						continue;
405

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

    
409
					$ikeid = $ph1ent['ikeid'];
410

    
411
					$ep = ipsec_get_phase1_src($ph1ent);
412
					if (!$ep)
413
						continue;
414

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

    
421
					$myid_type = $ph1ent['myid_type'];
422

    
423
					switch ($myid_type) {
424

    
425
						case "myaddress":
426
							$myid_type = "address";
427
							$myid_data = $ep;
428
							break;
429

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

    
435
						case "address";
436
							$myid_data = $ph1ent['myid_data'];
437
							break;
438

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

    
449
					$peerid_type = $ph1ent['peerid_type'];
450

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

    
457
						case "address";
458
							$peerid_data = $ph1ent['peerid_data'];
459
							break;
460

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

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

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

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

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

    
504
					$certline = '';
505

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

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

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

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

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

    
525
						chmod($certpath, 0600);
526

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

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

    
536
						chmod($keypath, 0600);
537

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

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

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

    
553
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
554

    
555
					}
556

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

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

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

    
574
					/* add remote section to configuration */
575

    
576
					$racoonconf .=<<<EOD
577

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

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

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

    
615
				/* begin sainfo */
616
				foreach ($a_phase2 as $ph2ent) {
617

    
618
					$ikeid = $ph2ent['ikeid'];
619

    
620
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
621
						continue;
622

    
623
					if (isset($ph1ent['disabled']))
624
						continue;
625

    
626
					if (isset($ph2ent['disabled']))
627
						continue;
628

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

    
632
					if ($ph2ent['mode'] == 'tunnel') {
633

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

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

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

    
654
					} else {
655

    
656
						$rgip = $rgmap[$ph1ent['remote-gateway']];
657

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

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

    
667
					if($ph2ent['protocol'] == 'esp') {
668

    
669
						$ealgos = '';
670

    
671
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
672

    
673
							$ealg_id = $ealg['name'];
674
							$ealg_kl = $ealg['keylen'];
675

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

    
711
						$ealgosline = "encryption_algorithm {$ealgos};";
712

    
713
					} else {
714

    
715
						$ealgosline = "encryption_algorithm null_enc;";
716
					}
717

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

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

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

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

    
748
EOD;
749
				}
750
				/* end sainfo */
751
			}
752
			/* end sainfo sections */
753

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

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

    
768
			$spdconf = "";
769

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

    
781
			foreach ($a_phase2 as $ph2ent) {
782

    
783
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
784
					continue;
785

    
786
				if (isset($ph1ent['mobile']))
787
					continue;
788

    
789
				if (isset($ph1ent['disabled']))
790
					continue;
791

    
792
				if (isset($ph2ent['disabled']))
793
					continue;
794

    
795
				$ep = ipsec_get_phase1_src($ph1ent);
796
				if (!$ep)
797
					continue;
798

    
799
				$rgip = $rgmap[$ph1ent['remote-gateway']];
800

    
801
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
802
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
803

    
804
				if($ph2ent['mode'] == "tunnel") {
805

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

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

    
812
				} else {
813

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

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

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

    
823
				}
824

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

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

    
856
			fwrite($fd, $spdconf);
857
			fclose($fd);
858
		}
859

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

    
883
			/* start dnswatch, if necessary */
884
			if (count($dnswatch_list) > 0) {
885
				$interval = 60;
886
				if ($ipseccfg['dns-interval'])
887
					$interval = $ipseccfg['dns-interval'];
888

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

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

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

    
905
	return 0;
906
}
907

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

    
917
	$ipseccfg = $config['ipsec'];
918

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

    
923
	/* wait for process to die */
924
	sleep(4);
925

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

    
929
	/* wait for flushing to finish */
930
	sleep(1);
931

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

    
938
}
939

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

    
945
	/* start pppoe server */
946
	vpn_pppoe_configure();
947

    
948
	/* setup l2tp */
949
	vpn_l2tp_configure();
950
}
951

    
952
function vpn_pptpd_configure() {
953
	global $config, $g;
954

    
955
	$syscfg = $config['system'];
956
	$pptpdcfg = $config['pptpd'];
957

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

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

    
967
		/* wait for process to die */
968
		sleep(3);
969

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

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

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

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

    
994
			$mpdconf = <<<EOD
995
pptpd:
996

    
997
EOD;
998

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

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

    
1005
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1006

    
1007
				$mpdconf .= <<<EOD
1008

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

    
1014
EOD;
1015
			}
1016

    
1017
			$mpdconf .=<<<EOD
1018

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

    
1039
EOD;
1040

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

    
1046
EOD;
1047
			}
1048

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

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

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

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

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

    
1086
EOD;
1087

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

    
1093
EOD;
1094
				}
1095
			}
1096

    
1097
			fwrite($fd, $mpdconf);
1098
			fclose($fd);
1099

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

    
1107
			$mpdlinks = "";
1108

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

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

    
1118
EOD;
1119
			}
1120

    
1121
			fwrite($fd, $mpdlinks);
1122
			fclose($fd);
1123

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

    
1131
			$mpdsecret = "";
1132

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

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

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

    
1145
			break;
1146

    
1147
		case 'redir' :
1148
			break;
1149
	}
1150

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

    
1154
	return 0;
1155
}
1156

    
1157
function vpn_pppoe_configure() {
1158
	global $config, $g;
1159

    
1160
	$syscfg = $config['system'];
1161
	$pppoecfg = $config['pppoe'];
1162

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

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

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

    
1176
		/* wait for process to die */
1177
		sleep(2);
1178

    
1179
	}
1180

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

    
1185
	switch ($pppoecfg['mode']) {
1186

    
1187
		case 'server' :
1188

    
1189
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1190

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

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

    
1206
EOD;
1207

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

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

    
1214
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1215

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

    
1222
				$mpdconf .=<<<EOD
1223

    
1224
pppoe{$i}:
1225
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1226
	{$isssue_ip_type}
1227
	load pppoe_standart
1228

    
1229
EOD;
1230
			}
1231

    
1232
			$mpdconf .=<<<EOD
1233

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

    
1260
EOD;
1261

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

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

    
1283
EOD;
1284

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

    
1289
EOD;
1290
				}
1291
			}
1292

    
1293
			fwrite($fd, $mpdconf);
1294
			fclose($fd);
1295

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

    
1303
			$mpdlinks = "";
1304

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

    
1315
EOD;
1316
			}
1317

    
1318
			fwrite($fd, $mpdlinks);
1319
			fclose($fd);
1320

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

    
1328
			$mpdsecret = "\n\n";
1329

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

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

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

    
1342
			break;
1343

    
1344
		case 'redir' :
1345
			break;
1346
	}
1347

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

    
1351
	return 0;
1352
}
1353

    
1354
function vpn_l2tp_configure() {
1355
	global $config, $g;
1356

    
1357
	$syscfg = $config['system'];
1358
	$l2tpcfg = $config['l2tp'];
1359

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

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

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

    
1373
		/* wait for process to die */
1374
		sleep(8);
1375

    
1376
	}
1377

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

    
1382
	switch ($l2tpcfg['mode']) {
1383

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

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

    
1400
EOD;
1401

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

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

    
1408
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1409

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

    
1416
				$mpdconf .=<<<EOD
1417

    
1418
l2tp{$i}:
1419
	new l2tp{$i} l2tp{$i}
1420
	{$isssue_ip_type}
1421
	load l2tp_standard
1422

    
1423
EOD;
1424
			}
1425

    
1426
			$mpdconf .=<<<EOD
1427

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

    
1444
EOD;
1445

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

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

    
1467
EOD;
1468

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

    
1473
EOD;
1474
				}
1475
			}
1476

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

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

    
1487
			$mpdlinks = "";
1488

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

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

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

    
1502
			fwrite($fd, $mpdlinks);
1503
			fclose($fd);
1504

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

    
1512
			$mpdsecret = "\n\n";
1513

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

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

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

    
1526
			break;
1527

    
1528
		case 'redir' :
1529
			break;
1530
	}
1531

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

    
1535
	return 0;
1536
}
1537

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

    
1545
	$ipseccfg = $config['ipsec'];
1546
	$a_phase1 = $config['ipsec']['phase1'];
1547
	$a_phase2 = $config['ipsec']['phase2'];
1548

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

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

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

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

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

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

    
1620
	$sad_arr = ipsec_dump_sad();
1621

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

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

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

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

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

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

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

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

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

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

    
1709
?>
(45-45/53)