Project

General

Profile

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

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

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

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

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

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

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

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

    
44
/* include all configuration functions */
45

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

    
49

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
260
		$pskconf = "";
261

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

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

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

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

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

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

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

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

    
294
		fwrite($fd, $pskconf);
295
		fclose($fd);
296
		chmod("{$g['varetc_path']}/psk.txt", 0600);
297
			
298
		/* begin racoon.conf */
299
		if ((is_array($a_phase1) && count($a_phase1)) ||
300
			(is_array($a_phase2) && count($a_phase2))) {
301

    
302
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
303
			if (!$fd) {
304
				printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
305
				return 1;
306
			}
307

    
308
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
309
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
310
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
311

    
312
			/* begin listen section */
313
			if (count($ipmap)) {
314
				$racoonconf .= "\nlisten\n";
315
				$racoonconf .= "{\n";
316
				$racoonconf .= "	adminsock \"/var/db/racoon/racoon.sock\" \"root\" \"wheel\" 0660;\n";
317
				foreach ($ipmap as $addr) {
318
					$racoonconf .= "\tisakmp {$addr} [500];\n";
319
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
320
				}
321
				$racoonconf .= "}\n\n";
322
			}
323

    
324
			/* begin mode_cfg section */
325
			if (is_array($a_client) && isset($a_client['enable'])) {
326

    
327
				$racoonconf .= "\nmode_cfg\n";
328
				$racoonconf .= "{\n";
329

    
330
				if ($a_client['user_source'])
331
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
332
				if ($a_client['group_source'])
333
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
334

    
335
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
336
					$pool_address = $a_client['pool_address'];
337
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
338

    
339
					$pool_address = long2ip(ip2long($pool_address)+1);
340
					$pool_size = ~ip2long($pool_netmask) - 2;
341

    
342
					$racoonconf .= "\tpool_size {$pool_size};\n";
343
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
344
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
345
				}
346

    
347
				if (isset($a_client['net_list'])) {
348

    
349
					$net_list = '';
350

    
351
					foreach ($a_phase2 as $ph2ent) {
352

    
353
						if (isset($ph2ent['disabled']))
354
							continue;
355

    
356
						if (!isset($ph2ent['mobile']))
357
							continue;
358

    
359
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
360

    
361
						if ($net_list)
362
							$net_list .= ", ";
363
						$net_list .= $localid;
364
					}
365

    
366
					if ($net_list)
367
						$racoonconf .= "\tsplit_network include {$net_list};\n";
368
				}
369

    
370
				if ($a_client['dns_server1'])
371
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
372
				if ($a_client['dns_server2'])
373
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
374
				if ($a_client['dns_server3'])
375
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
376
				if ($a_client['dns_server4'])
377
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
378

    
379
				if ($a_client['wins_server1'])
380
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
381
				if ($a_client['wins_server2'])
382
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
383

    
384
				if ($a_client['dns_domain'])
385
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
386

    
387
				if ($a_client['pfs_group'])
388
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
389

    
390
				if ($a_client['login_banner']) {
391
					$fn = "{$g['varetc_path']}/racoon.motd";
392
					$fd1 = fopen($fn, "w");
393
					if (!$fd1) {
394
						printf("Error: cannot open server{$fn} in vpn.\n");
395
						return 1;
396
					}
397

    
398
					fwrite($fd1, $a_client['login_banner']);
399
					fclose($fd1);
400

    
401
					$racoonconf .= "\tbanner \"{$fn}\";\n";
402
				}
403

    
404
				$racoonconf .= "}\n\n";
405
			}
406
			/* end mode_cfg section */
407

    
408
			/* begin remote sections */
409
			if (is_array($a_phase1) && count($a_phase1)) {
410
				/* begin remote */
411
				foreach ($a_phase1 as $ph1ent) {
412

    
413
					if (isset($ph1ent['disabled']))
414
						continue;
415

    
416
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
417
						continue;
418

    
419
					$ikeid = $ph1ent['ikeid'];
420

    
421
					$ep = ipsec_get_phase1_src($ph1ent);
422
					if (!$ep)
423
						continue;
424

    
425
					if (!isset($ph1ent['mobile'])) {
426
						$rgip = $rgmap[$ph1ent['remote-gateway']];
427
						if (!$rgip)
428
							continue;
429
					}
430

    
431
					$myid_type = $ph1ent['myid_type'];
432

    
433
					switch ($myid_type) {
434

    
435
						case "myaddress":
436
							$myid_type = "address";
437
							$myid_data = $ep;
438
							break;
439

    
440
						case "dyn_dns":
441
							$myid_type = "address";
442
							$myid_data = gethostbyname($ph1ent['myid_data']);
443
							break;
444

    
445
						case "address";
446
							$myid_data = $ph1ent['myid_data'];
447
							break;
448

    
449
						case "fqdn";
450
						case "keyid tag";
451
						case "user_fqdn";
452
						case "asn1dn";
453
							$myid_data = $ph1ent['myid_data'];
454
							if( $myid_data )
455
								$myid_data = "\"".$myid_data."\"";
456
							break;
457
					}
458

    
459
					$peerid_type = $ph1ent['peerid_type'];
460

    
461
					switch ($peerid_type) {
462
						case "peeraddress":
463
							$peerid_type = "address";
464
							$peerid_data = $rgip;
465
							break;
466

    
467
						case "address";
468
							$peerid_data = $ph1ent['peerid_data'];
469
							break;
470

    
471
						case "fqdn";
472
						case "keyid tag";
473
						case "user_fqdn";
474
						case "asn1dn";
475
							$peerid_data = $ph1ent['peerid_data'];
476
							if( $peerid_data )
477
								$peerid_data = "\"".$peerid_data."\"";
478
							break;
479
					}
480

    
481
					$natt = "off";
482
					if (isset($ph1ent['nat_traversal']))
483
						$natt = $ph1ent['nat_traversal'];
484

    
485
					$init = "on";
486
					$genp = "off";
487
					if (isset($ph1ent['mobile'])) {
488
						$rgip = "anonymous";
489
						$init = "off";
490
						$genp = "unique";
491
					}
492

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

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

    
505
					$certline = '';
506

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

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

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

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

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

    
526
						chmod($certpath, 0600);
527

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

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

    
537
						chmod($keypath, 0600);
538

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

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

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

    
554
					/* add remote section to configuration */
555

    
556
					$racoonconf .=<<<EOD
557

    
558
remote {$rgip}
559
{
560
	ph1id {$ikeid};
561
	exchange_mode {$ph1ent['mode']};
562
	my_identifier {$myid_type} {$myid_data};
563
	peers_identifier {$peerid_type} {$peerid_data};
564
	ike_frag on;
565
	generate_policy = {$genp};
566
	initial_contact = {$init};
567
	nat_traversal = {$natt};
568
	{$certline}
569
	{$dpdline1}
570
	{$dpdline2}
571
	support_proxy on;
572
	proposal_check claim;
573

    
574
	proposal
575
	{
576
		authentication_method {$authmethod};
577
		encryption_algorithm ${ealgos};
578
		hash_algorithm {$ph1ent['hash-algorithm']};
579
		dh_group {$ph1ent['dhgroup']};
580
		${lifeline}
581
	}
582
}
583

    
584
EOD;
585
				}
586
				/* end remote */
587
			}
588
			/* end remote sections */
589
		
590
			/* begin sainfo sections */
591
			if (is_array($a_phase2) && count($a_phase2)) {
592

    
593
				/* begin sainfo */
594
				foreach ($a_phase2 as $ph2ent) {
595

    
596
					$ikeid = $ph2ent['ikeid'];
597

    
598
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
599
						continue;
600

    
601
					if (isset($ph1ent['disabled']))
602
						continue;
603

    
604
					if (isset($ph2ent['disabled']))
605
						continue;
606

    
607
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
608
						continue;
609

    
610
					if ($ph2ent['mode'] == 'tunnel') {
611

    
612
						$localid_type = $ph2ent['localid']['type'];
613
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
614
						if ($localid_type == "none")
615
							$localid_spec = " ";
616
						else if ($localid_type != "address") {
617
							$localid_type = "subnet";
618
							$localid_spec = $localid_type." ".$localid_data." any";
619
						}
620

    
621
						if (!isset($ph2ent['mobile'])) {
622
							$remoteid_type = $ph2ent['remoteid']['type'];
623
							if ($remoteid_type != "address")
624
								$remoteid_type = "subnet";
625

    
626
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
627
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
628
						} else
629
							$remoteid_spec = "anonymous";
630

    
631
					} else {
632

    
633
						$rgip = $rgmap[$ph1ent['remote-gateway']];
634

    
635
						$localid_data = ipsec_get_phase1_src($ph1ent);
636
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
637
						$localid_spec = "address {$localid_data}";
638

    
639
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
640
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
641
						$remoteid_spec = "address {$remoteid_data}";
642
					}
643

    
644
					if($ph2ent['protocol'] == 'esp') {
645

    
646
						$ealgos = '';
647

    
648
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
649

    
650
							$ealg_id = $ealg['name'];
651
							$ealg_kl = $ealg['keylen'];
652

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

    
688
						$ealgosline = "encryption_algorithm {$ealgos};";
689

    
690
					} else {
691

    
692
						$ealgosline = "encryption_algorithm null_enc;";
693
					}
694

    
695
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
696
					$halgosline = "authentication_algorithm {$halgos};";
697

    
698
					$pfsline = '';
699
					if ($ph2ent['pfsgroup'])
700
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
701
					if (isset($a_client['pfs_group'])) {
702
						$pfsline = '';
703
						if ($a_client['pfs_group'])
704
							$pfsline = "pfs_group {$a_client['pfs_group']};";
705
					}
706

    
707
					$lifeline = '';
708
					if ($ph2ent['lifetime'])
709
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
710

    
711
					/* add sainfo section to configuration */
712
					
713
					$racoonconf .=<<<EOD
714
					
715
sainfo {$localid_spec} {$remoteid_spec}
716
{
717
	remoteid {$ikeid};
718
	{$ealgosline}
719
	{$halgosline}
720
	{$pfsline}
721
	{$lifeline}
722
	compression_algorithm deflate;
723
}
724

    
725
EOD;
726
				}
727
				/* end sainfo */
728
			}
729
			/* end sainfo sections */
730

    
731
			fwrite($fd, $racoonconf);
732
			fclose($fd);
733
		}
734
		/* end racoon.conf */
735

    
736
		/* generate IPsec policies */
737
		if (is_array($a_phase2) && count($a_phase2)) {
738
			/* generate spd.conf */
739
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
740
			if (!$fd) {
741
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
742
				return 1;
743
			}
744

    
745
			$spdconf = "";
746

    
747
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
748
			if ($config['interfaces']['lan']) {
749
				$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
750
				$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
751
			}
752

    
753
			foreach ($a_phase2 as $ph2ent) {
754

    
755
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
756
					continue;
757

    
758
				if (isset($ph1ent['mobile']))
759
					continue;
760

    
761
				if (isset($ph1ent['disabled']))
762
					continue;
763

    
764
				if (isset($ph2ent['disabled']))
765
					continue;
766

    
767
				$ep = ipsec_get_phase1_src($ph1ent);
768
				if (!$ep)
769
					continue;
770

    
771
				$rgip = $rgmap[$ph1ent['remote-gateway']];
772

    
773
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
774
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
775

    
776
				if (isset ($ph2ent['creategif'])) {
777
					$number_of_gifs = find_last_gif_device();
778
					$number_of_gifs++;
779
					$curwanip = get_interface_ip();
780
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
781
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
782
							if ($sasyncd['ip'] <> "")
783
								$curwanip = $sasyncd['ip'];
784
						}
785
					}
786
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
787
					if ($config['interfaces']['lan'])
788
						mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
789
				}
790

    
791
				if($ph2ent['mode'] == "tunnel") {
792

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

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

    
799
				} else {
800

    
801
					$localid_data = ipsec_get_phase1_src($ph1ent);
802
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
803

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

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

    
810
				}
811

    
812
				/* static route needed? */
813
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
814
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
815
				else
816
					$parentinterface = $ph1ent['interface'];
817

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

    
843
			fwrite($fd, $spdconf);
844
			fclose($fd);
845
		}
846

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

    
870
			/* start dnswatch, if necessary */
871
			if (count($dnswatch_list) > 0) {
872
				$interval = 60;
873
				if ($ipseccfg['dns-interval'])
874
					$interval = $ipseccfg['dns-interval'];
875

    
876
				$hostnames = "";
877
				array_unique($dnswatch_list);
878
				$hostnames = implode("\n", $dnswatch_list);
879
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
880

    
881
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
882
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
883
			}
884
		}
885
	
886
		vpn_ipsec_failover_configure();
887

    
888
		if ($g['booting'])
889
			echo "done\n";
890
	}
891

    
892
	return 0;
893
}
894

    
895
/* Forcefully restart IPsec
896
 * This is required for when dynamic interfaces reload
897
 * For all other occasions the normal vpn_ipsec_configure()
898
 * will gracefully reload the settings without restarting
899
 */
900
function vpn_ipsec_force_reload() {
901
	global $config;
902
	global $g;
903

    
904
	$ipseccfg = $config['ipsec'];
905

    
906
	/* kill racoon */
907
	if(is_process_running("racoon"))
908
		mwexec("/usr/bin/killall racoon", true);
909

    
910
	/* wait for process to die */
911
	sleep(4);
912

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

    
916
	/* wait for flushing to finish */
917
	sleep(1);
918

    
919
	/* if ipsec is enabled, start up again */
920
	if (isset($ipseccfg['enable'])) {
921
		log_error("Forcefully reloading IPsec racoon daemon");
922
		vpn_ipsec_configure();
923
	}
924

    
925
}
926

    
927
/* master setup for vpn (mpd) */
928
function vpn_setup() {
929
	/* start pptpd */
930
	vpn_pptpd_configure();
931

    
932
	/* start pppoe server */
933
	vpn_pppoe_configure();
934

    
935
	/* setup l2tp */
936
	vpn_l2tp_configure();
937
}
938

    
939
function vpn_pptpd_configure() {
940
	global $config, $g;
941

    
942
	$syscfg = $config['system'];
943
	$pptpdcfg = $config['pptpd'];
944

    
945
	if ($g['booting']) {
946
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
947
			return 0;
948

    
949
		echo "Configuring PPTP VPN service... ";
950
	} else {
951
		/* kill mpd */
952
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
953

    
954
		/* wait for process to die */
955
		sleep(3);
956

    
957
		if (is_process_running("mpd -b")) {
958
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
959
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
960
		}
961

    
962
		/* remove mpd.conf, if it exists */
963
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
964
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
965
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
966
	}
967

    
968
	/* make sure pptp-vpn directory exists */
969
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
970
		mkdir("{$g['varetc_path']}/pptp-vpn");
971

    
972
	switch ($pptpdcfg['mode']) {
973
		case 'server' :
974
			/* write mpd.conf */
975
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
976
			if (!$fd) {
977
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
978
				return 1;
979
			}
980

    
981
			$mpdconf = <<<EOD
982
pptpd:
983

    
984
EOD;
985

    
986
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
987
				$mpdconf .= "	load pt{$i}\n";
988
			}
989

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

    
992
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
993

    
994
				$mpdconf .= <<<EOD
995

    
996
pt{$i}:
997
	new -i pptpd{$i} pt{$i} pt{$i}
998
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
999
	load pts
1000

    
1001
EOD;
1002
			}
1003

    
1004
			$mpdconf .=<<<EOD
1005

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

    
1026
EOD;
1027

    
1028
			if (!isset ($pptpdcfg['req128'])) {
1029
				$mpdconf .=<<<EOD
1030
	set ccp yes mpp-e40
1031
	set ccp yes mpp-e56
1032

    
1033
EOD;
1034
			}
1035

    
1036
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
1037
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
1038
			if (is_array($pptpdcfg['dnsserver']) && ($pptpdcfg['dnsserver'][0])) {
1039
				$mpdconf .= "	set ipcp dns " . join(" ", $pptpdcfg['dnsserver']) . "\n";
1040
			} else
1041
				if (isset ($config['dnsmasq']['enable'])) {
1042
					$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1043
					if ($syscfg['dnsserver'][0])
1044
						$mpdconf .= " " . $syscfg['dnsserver'][0];
1045
					$mpdconf .= "\n";
1046
				} else
1047
					if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1048
						$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1049
					}
1050

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

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

    
1064
EOD;
1065
			}
1066
			$mpdconf .=<<<EOD
1067
	set radius retries 3
1068
	set radius timeout 10
1069
	set auth enable radius-auth
1070

    
1071
EOD;
1072

    
1073
				if (isset ($pptpdcfg['radius']['accounting'])) {
1074
					$mpdconf .=<<<EOD
1075
	set auth enable radius-acct
1076
	set radius acct-update 300
1077

    
1078
EOD;
1079
				}
1080
			}
1081

    
1082
			fwrite($fd, $mpdconf);
1083
			fclose($fd);
1084

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

    
1092
			$mpdlinks = "";
1093

    
1094
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1095
				$mpdlinks .=<<<EOD
1096

    
1097
pt{$i}:
1098
	set link type pptp
1099
	set pptp enable incoming
1100
	set pptp disable originate
1101
	set pptp disable windowing
1102

    
1103
EOD;
1104
			}
1105

    
1106
			fwrite($fd, $mpdlinks);
1107
			fclose($fd);
1108

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

    
1116
			$mpdsecret = "";
1117

    
1118
			if (is_array($pptpdcfg['user'])) {
1119
				foreach ($pptpdcfg['user'] as $user)
1120
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1121
			}
1122

    
1123
			fwrite($fd, $mpdsecret);
1124
			fclose($fd);
1125
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1126

    
1127
			/* fire up mpd */
1128
			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");
1129

    
1130
			break;
1131

    
1132
		case 'redir' :
1133
			break;
1134
	}
1135

    
1136
	if ($g['booting'])
1137
		echo "done\n";
1138

    
1139
	return 0;
1140
}
1141

    
1142
function vpn_pppoe_configure() {
1143
	global $config, $g;
1144

    
1145
	$syscfg = $config['system'];
1146
	$pppoecfg = $config['pppoe'];
1147

    
1148
	/* create directory if it does not exist */
1149
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1150
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1151

    
1152
	if ($g['booting']) {
1153
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1154
			return 0;
1155

    
1156
		echo "Configuring PPPoE VPN service... ";
1157
	} else {
1158
		/* kill mpd */
1159
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1160

    
1161
		/* wait for process to die */
1162
		sleep(2);
1163

    
1164
	}
1165

    
1166
	/* make sure pppoe-vpn directory exists */
1167
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1168
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1169

    
1170
	switch ($pppoecfg['mode']) {
1171

    
1172
		case 'server' :
1173

    
1174
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1175

    
1176
			if ($pppoecfg['paporchap'] == "chap")
1177
				$paporchap = "set link enable chap";
1178
			else
1179
				$paporchap = "set link enable pap";
1180

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

    
1191
EOD;
1192

    
1193
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1194
				$mpdconf .= "	load pppoe{$i}\n";
1195
			}
1196

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

    
1199
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1200

    
1201
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1202
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1203
				} else {
1204
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1205
				}
1206

    
1207
				$mpdconf .=<<<EOD
1208

    
1209
pppoe{$i}:
1210
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1211
	{$isssue_ip_type}
1212
	load pppoe_standart
1213

    
1214
EOD;
1215
			}
1216

    
1217
			$mpdconf .=<<<EOD
1218

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

    
1245
EOD;
1246

    
1247
			if (isset ($config['dnsmasq']['enable'])) {
1248
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1249
				if ($syscfg['dnsserver'][0])
1250
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1251
				$mpdconf .= "\n";
1252
			} else
1253
				if (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 = long2ip(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 (isset ($config['dnsmasq']['enable'])) {
1428
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1429
				if ($syscfg['dnsserver'][0])
1430
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1431
				$mpdconf .= "\n";
1432
			} else
1433
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1434
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1435
				}
1436

    
1437
			if (isset ($l2tpcfg['radius']['enable'])) {
1438
				$mpdconf .=<<<EOD
1439
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1440
	set radius retries 3
1441
	set radius timeout 10
1442
	set auth enable radius-auth
1443

    
1444
EOD;
1445

    
1446
				if (isset ($l2tpcfg['radius']['accounting'])) {
1447
					$mpdconf .=<<<EOD
1448
	set auth enable radius-acct
1449

    
1450
EOD;
1451
				}
1452
			}
1453

    
1454
			fwrite($fd, $mpdconf);
1455
			fclose($fd);
1456

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

    
1464
			$mpdlinks = "";
1465

    
1466
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1467
				$mpdlinks .=<<<EOD
1468

    
1469
l2tp{$i}:
1470
	set link type l2tp
1471
        set l2tp enable incoming
1472
        set l2tp disable originate
1473

    
1474
EOD;
1475
			if (!empty($l2tpcfg['secret']))
1476
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1477
			}
1478

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

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

    
1489
			$mpdsecret = "\n\n";
1490

    
1491
			if (is_array($l2tpcfg['user'])) {
1492
				foreach ($l2tpcfg['user'] as $user)
1493
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1494
			}
1495

    
1496
			fwrite($fd, $mpdsecret);
1497
			fclose($fd);
1498
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1499

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

    
1503
			break;
1504

    
1505
		case 'redir' :
1506
			break;
1507
	}
1508

    
1509
	if ($g['booting'])
1510
		echo "done\n";
1511

    
1512
	return 0;
1513
}
1514

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

    
1522
	$ipseccfg = $config['ipsec'];
1523
	$a_phase1 = $config['ipsec']['phase1'];
1524
	$a_phase2 = $config['ipsec']['phase2'];
1525

    
1526
	if (isset($ipseccfg['disable'])) {
1527
		return true;
1528
	}
1529

    
1530
	/* Walk the Ipsec tunnel array */
1531
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1532
		return;
1533
	}
1534

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

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

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

    
1589
	/* if we are not passed a old tunnel array we create one */
1590
	if(empty($old_phase1)) {
1591
		$old_phase1 = $phase1;
1592
	}
1593
	if(empty($old_phase2)) {
1594
		$old_phase2 = $phase2;
1595
	}
1596

    
1597
	$sad_arr = ipsec_dump_sad();
1598

    
1599
	$ep = ipsec_get_phase1_src($phase1);
1600
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1601
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1602

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

    
1606
	$old_ep = ipsec_get_phase1_src($old_phase1);
1607
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1608
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1609

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

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

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

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

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

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

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

    
1686
?>
(44-44/50)