Project

General

Profile

Download (45.7 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']['preferredoldsa']))
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
	$lanip = get_interface_ip("lan");
100
	$lansn = get_interface_subnet("lan");
101
	$lansa = gen_subnet($lanip, $lansn);
102

    
103
	if (!isset($ipseccfg['enable'])) {
104
		mwexec("/sbin/ifconfig enc0 down");
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
		/* send a SIGKILL to be sure */
115
		sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
116

    
117
		/* flush SPD and SAD */
118
		mwexec("/usr/local/sbin/setkey -FP");
119
		mwexec("/usr/local/sbin/setkey -F");
120
		
121
		/* disallow IPSEC, it is off */
122
//		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
123

    
124
		return true;
125
	} else {
126
		mwexec("/sbin/ifconfig enc0 up");
127

    
128
		if ($g['booting'])
129
			echo "Configuring IPsec VPN... ";
130

    
131
		/* fastforwarding is not compatible with ipsec tunnels */
132
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
133

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

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

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

    
149
				$ep = ipsec_get_phase1_src($ph1ent);
150
				if (!$ep)
151
					continue;
152

    
153
				if(!in_array($ep,$ipmap))
154
					$ipmap[] = $ep;
155

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

    
159
				if (isset ($ph1ent['mobile']))
160
					continue;
161

    
162
				$rg = $ph1ent['remote-gateway'];
163

    
164
				if (!is_ipaddr($rg)) {
165
					$dnswatch_list[] = $rg;
166
					add_hostname_to_watch($rg);
167
					$rg = resolve_retry($rg);
168
					if (!$rg)
169
						continue;
170
				}
171

    
172
				$rgmap[$ph1ent['remote-gateway']] = $rg;
173

    
174
				/* step through each phase2 entry */
175
				$ipsecpinghosts = "";
176
				foreach ($a_phase2 as $ph2ent) {
177

    
178
					$ikeid = $ph2ent['ikeid'];
179

    
180
					if (isset($ph2ent['disabled']))
181
						continue;
182

    
183
					if ($ikeid != $ph1ent['ikeid'])
184
						continue;
185

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

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

    
239
		$pskconf = "";
240

    
241
		if (is_array($a_phase1) && count($a_phase1)) {
242
			foreach ($a_phase1 as $ph1ent) {
243

    
244
				if (isset($ph1ent['disabled']))
245
					continue;
246

    
247
				if (strstr($ph1ent['authentication_method'],'rsa'))
248
					continue;
249

    
250
				$peerid_type = $ph1ent['peerid_type'];
251

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

    
258
					case "address";
259
						$peerid_data = $ph1ent['peerid_data'];
260
						break;
261

    
262
					case "fqdn";
263
					case "keyid tag";
264
					case "user_fqdn";
265
						$peerid_data = $ph1ent['peerid_data'];
266
						break;
267
				}
268

    
269
				$pskconf .= "{$peerid_data}\t{$ph1ent['pre-shared-key']}\n";
270
			}
271
		}
272

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

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

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

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

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

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

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

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

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

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

    
332
					$pool_address = long2ip32(ip2long($pool_address)+1);
333
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
334

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

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

    
342
					$net_list = '';
343

    
344
					foreach ($a_phase2 as $ph2ent) {
345

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
426
					switch ($myid_type) {
427

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

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

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

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

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

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

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

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

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

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

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

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

    
507
					$certline = '';
508

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

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

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

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

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

    
528
						chmod($certpath, 0600);
529

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

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

    
539
						chmod($keypath, 0600);
540

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

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

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

    
556
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
557
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
558
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
559
					}
560

    
561
					/* add remote section to configuration */
562

    
563
					$racoonconf .=<<<EOD
564

    
565
remote {$rgip}
566
{
567
	ph1id {$ikeid};
568
	exchange_mode {$ph1ent['mode']};
569
	my_identifier {$myid_type} {$myid_data};
570
	{$peerid_spec}
571
	ike_frag on;
572
	generate_policy = {$genp};
573
	initial_contact = {$init};
574
	nat_traversal = {$natt};
575
	{$certline}
576
	{$dpdline1}
577
	{$dpdline2}
578
	support_proxy on;
579
	proposal_check {$pcheck};
580
	{$passive}
581

    
582
	proposal
583
	{
584
		authentication_method {$authmethod};
585
		encryption_algorithm ${ealgos};
586
		hash_algorithm {$ph1ent['hash-algorithm']};
587
		dh_group {$ph1ent['dhgroup']};
588
		${lifeline}
589
	}
590
}
591

    
592
EOD;
593
				}
594
				/* end remote */
595
			}
596
			/* end remote sections */
597
		
598
			/* begin sainfo sections */
599
			if (is_array($a_phase2) && count($a_phase2)) {
600

    
601
				/* begin sainfo */
602
				foreach ($a_phase2 as $ph2ent) {
603

    
604
					$ikeid = $ph2ent['ikeid'];
605

    
606
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
607
						continue;
608

    
609
					if (isset($ph1ent['disabled']))
610
						continue;
611

    
612
					if (isset($ph2ent['disabled']))
613
						continue;
614

    
615
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
616
						continue;
617

    
618
					if ($ph2ent['mode'] == 'tunnel') {
619

    
620
						$localid_type = $ph2ent['localid']['type'];
621
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
622
						/* Do not print localid in some cases, such as a pure-psk mobile tunnel */
623
						if (($localid_type == "none") || ($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))
624
							$localid_spec = " ";
625
						else if ($localid_type != "address") {
626
							$localid_type = "subnet";
627
							$localid_spec = $localid_type." ".$localid_data." any";
628
						}
629

    
630
						if (!isset($ph2ent['mobile'])) {
631
							$remoteid_type = $ph2ent['remoteid']['type'];
632
							if ($remoteid_type != "address")
633
								$remoteid_type = "subnet";
634

    
635
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
636
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
637
						} else
638
							$remoteid_spec = "anonymous";
639

    
640
					} else {
641

    
642
						$rgip = $rgmap[$ph1ent['remote-gateway']];
643

    
644
						$localid_data = ipsec_get_phase1_src($ph1ent);
645
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
646
						$localid_spec = "address {$localid_data}";
647

    
648
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
649
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
650
						$remoteid_spec = "address {$remoteid_data}";
651
					}
652

    
653
					if($ph2ent['protocol'] == 'esp') {
654

    
655
						$ealgos = '';
656

    
657
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
658

    
659
							$ealg_id = $ealg['name'];
660
							$ealg_kl = $ealg['keylen'];
661

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

    
697
						$ealgosline = "encryption_algorithm {$ealgos};";
698

    
699
					} else {
700

    
701
						$ealgosline = "encryption_algorithm null_enc;";
702
					}
703

    
704
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
705
					$halgosline = "authentication_algorithm {$halgos};";
706

    
707
					$pfsline = '';
708
					if ($ph2ent['pfsgroup'])
709
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
710
					if (isset($a_client['pfs_group'])) {
711
						$pfsline = '';
712
						if ($a_client['pfs_group'])
713
							$pfsline = "pfs_group {$a_client['pfs_group']};";
714
					}
715

    
716
					$lifeline = '';
717
					if ($ph2ent['lifetime'])
718
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
719

    
720
					/* add sainfo section to configuration */
721
					
722
					$racoonconf .=<<<EOD
723
					
724
sainfo {$localid_spec} {$remoteid_spec}
725
{
726
	remoteid {$ikeid};
727
	{$ealgosline}
728
	{$halgosline}
729
	{$pfsline}
730
	{$lifeline}
731
	compression_algorithm deflate;
732
}
733

    
734
EOD;
735
				}
736
				/* end sainfo */
737
			}
738
			/* end sainfo sections */
739

    
740
			fwrite($fd, $racoonconf);
741
			fclose($fd);
742
		}
743
		/* end racoon.conf */
744

    
745
		/* generate IPsec policies */
746
		if (is_array($a_phase2) && count($a_phase2)) {
747
			/* generate spd.conf */
748
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
749
			if (!$fd) {
750
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
751
				return 1;
752
			}
753

    
754
			$spdconf = "";
755

    
756
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
757
			if ($config['interfaces']['lan']) {
758
				$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
759
				$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
760
			}
761

    
762
			foreach ($a_phase2 as $ph2ent) {
763

    
764
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
765
					continue;
766

    
767
				if (isset($ph1ent['mobile']))
768
					continue;
769

    
770
				if (isset($ph1ent['disabled']))
771
					continue;
772

    
773
				if (isset($ph2ent['disabled']))
774
					continue;
775

    
776
				$ep = ipsec_get_phase1_src($ph1ent);
777
				if (!$ep)
778
					continue;
779

    
780
				$rgip = $rgmap[$ph1ent['remote-gateway']];
781

    
782
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
783
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
784

    
785
				if($ph2ent['mode'] == "tunnel") {
786

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

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

    
793
				} else {
794

    
795
					$localid_data = ipsec_get_phase1_src($ph1ent);
796
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
797

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

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

    
804
				}
805

    
806
				/* static route needed? */
807
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
808
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
809
				else
810
					$parentinterface = $ph1ent['interface'];
811

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

    
837
			fwrite($fd, $spdconf);
838
			fclose($fd);
839
		}
840

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

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

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

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

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

    
886
	return 0;
887
}
888

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

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

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

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

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

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

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

    
919
}
920

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

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

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

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

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

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

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

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

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

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

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

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

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

    
978
EOD;
979

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

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

    
986
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
987

    
988
				$mpdconf .= <<<EOD
989

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

    
995
EOD;
996
			}
997

    
998
			$mpdconf .=<<<EOD
999

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

    
1020
EOD;
1021

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

    
1027
EOD;
1028
			}
1029

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

    
1033
			if (!empty($pptpdcfg['dns1'])) {
1034
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1035
				if (!empty($pptpdcfg['dns2']))
1036
					$mpdconf .= " " . $pptpdcfg['dns2'];
1037
				$mpdconf .= "\n";
1038
			} elseif (isset ($config['dnsmasq']['enable'])) {
1039
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1040
				if ($syscfg['dnsserver'][0])
1041
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1042
				$mpdconf .= "\n";
1043
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1044
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1045
			}
1046

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

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

    
1060
EOD;
1061
			}
1062
			$mpdconf .=<<<EOD
1063
	set radius retries 3
1064
	set radius timeout 10
1065
	set auth enable radius-auth
1066

    
1067
EOD;
1068

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

    
1074
EOD;
1075
				}
1076
			}
1077

    
1078
			fwrite($fd, $mpdconf);
1079
			fclose($fd);
1080

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

    
1088
			$mpdlinks = "";
1089

    
1090
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1091
				$mpdlinks .=<<<EOD
1092

    
1093
pt{$i}:
1094
	set link type pptp
1095
	set pptp enable incoming
1096
	set pptp disable originate
1097
	set pptp disable windowing
1098

    
1099
EOD;
1100
			}
1101

    
1102
			fwrite($fd, $mpdlinks);
1103
			fclose($fd);
1104

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

    
1112
			$mpdsecret = "";
1113

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

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

    
1123
			/* fire up mpd */
1124
			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");
1125

    
1126
			break;
1127

    
1128
		case 'redir' :
1129
			break;
1130
	}
1131

    
1132
	if ($g['booting'])
1133
		echo "done\n";
1134

    
1135
	return 0;
1136
}
1137

    
1138
function vpn_pppoe_configure() {
1139
	global $config, $g;
1140

    
1141
	$syscfg = $config['system'];
1142
	$pppoecfg = $config['pppoe'];
1143

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

    
1148
	if ($g['booting']) {
1149
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1150
			return 0;
1151

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

    
1157
		/* wait for process to die */
1158
		sleep(2);
1159

    
1160
	}
1161

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

    
1166
	switch ($pppoecfg['mode']) {
1167

    
1168
		case 'server' :
1169

    
1170
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1171

    
1172
			if ($pppoecfg['paporchap'] == "chap")
1173
				$paporchap = "set link enable chap";
1174
			else
1175
				$paporchap = "set link enable pap";
1176

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

    
1187
EOD;
1188

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

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

    
1195
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1196

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

    
1203
				$mpdconf .=<<<EOD
1204

    
1205
pppoe{$i}:
1206
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1207
	{$isssue_ip_type}
1208
	load pppoe_standart
1209

    
1210
EOD;
1211
			}
1212

    
1213
			$mpdconf .=<<<EOD
1214

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

    
1241
EOD;
1242

    
1243
			if (!empty($pppoecfg['dns1'])) {
1244
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1245
				if (!empty($pppoecfg['dns2']))
1246
					$mpdconf .= " " . $pppoecfg['dns2'];
1247
				$mpdconf .= "\n";
1248
			} elseif (isset ($config['dnsmasq']['enable'])) {
1249
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1250
				if ($syscfg['dnsserver'][0])
1251
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1252
				$mpdconf .= "\n";
1253
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1254
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1255
			}
1256

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

    
1264
EOD;
1265

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

    
1270
EOD;
1271
				}
1272
			}
1273

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

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

    
1284
			$mpdlinks = "";
1285

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

    
1296
EOD;
1297
			}
1298

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

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

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

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

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

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

    
1323
			break;
1324

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

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

    
1332
	return 0;
1333
}
1334

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

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

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

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

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

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

    
1357
	}
1358

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

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

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

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

    
1381
EOD;
1382

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

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

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

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

    
1397
				$mpdconf .=<<<EOD
1398

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

    
1404
EOD;
1405
			}
1406

    
1407
			$mpdconf .=<<<EOD
1408

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

    
1425
EOD;
1426

    
1427
			if (!empty($l2tpcfg['dns1'])) {
1428
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1429
				if (!empty($l2tpcfg['dns2']))
1430
					$mpdconf .= " " . $l2tpcfg['dns2'];
1431
				$mpdconf .= "\n";
1432
			} elseif (isset ($config['dnsmasq']['enable'])) {
1433
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1434
				if ($syscfg['dnsserver'][0])
1435
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1436
				$mpdconf .= "\n";
1437
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1438
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1439
			}
1440

    
1441
			if (isset ($l2tpcfg['radius']['enable'])) {
1442
				$mpdconf .=<<<EOD
1443
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1444
	set radius retries 3
1445
	set radius timeout 10
1446
	set auth enable radius-auth
1447

    
1448
EOD;
1449

    
1450
				if (isset ($l2tpcfg['radius']['accounting'])) {
1451
					$mpdconf .=<<<EOD
1452
	set auth enable radius-acct
1453

    
1454
EOD;
1455
				}
1456
			}
1457

    
1458
			fwrite($fd, $mpdconf);
1459
			fclose($fd);
1460

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

    
1468
			$mpdlinks = "";
1469

    
1470
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1471
				$mpdlinks .=<<<EOD
1472

    
1473
l2tp{$i}:
1474
	set link type l2tp
1475
        set l2tp enable incoming
1476
        set l2tp disable originate
1477

    
1478
EOD;
1479
			if (!empty($l2tpcfg['secret']))
1480
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1481
			}
1482

    
1483
			fwrite($fd, $mpdlinks);
1484
			fclose($fd);
1485

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

    
1493
			$mpdsecret = "\n\n";
1494

    
1495
			if (is_array($l2tpcfg['user'])) {
1496
				foreach ($l2tpcfg['user'] as $user)
1497
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1498
			}
1499

    
1500
			fwrite($fd, $mpdsecret);
1501
			fclose($fd);
1502
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1503

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

    
1507
			break;
1508

    
1509
		case 'redir' :
1510
			break;
1511
	}
1512

    
1513
	if ($g['booting'])
1514
		echo "done\n";
1515

    
1516
	return 0;
1517
}
1518

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

    
1526
	$ipseccfg = $config['ipsec'];
1527
	$a_phase1 = $config['ipsec']['phase1'];
1528
	$a_phase2 = $config['ipsec']['phase2'];
1529

    
1530
	if (isset($ipseccfg['disable'])) {
1531
		return true;
1532
	}
1533

    
1534
	/* Walk the Ipsec tunnel array */
1535
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1536
		return;
1537
	}
1538

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

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

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

    
1593
	/* if we are not passed a old tunnel array we create one */
1594
	if(empty($old_phase1)) {
1595
		$old_phase1 = $phase1;
1596
	}
1597
	if(empty($old_phase2)) {
1598
		$old_phase2 = $phase2;
1599
	}
1600

    
1601
	$sad_arr = ipsec_dump_sad();
1602

    
1603
	$ep = ipsec_get_phase1_src($phase1);
1604
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1605
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1606

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

    
1610
	$old_ep = ipsec_get_phase1_src($old_phase1);
1611
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1612
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1613

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

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

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

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

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

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

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

    
1690
?>
(44-44/51)