Project

General

Profile

Download (48.6 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
	vpn_ipsec_configure_preferoldsa();
90

    
91
	$syscfg = $config['system'];
92
	$ipseccfg = $config['ipsec'];
93
	$a_phase1 = $config['ipsec']['phase1'];
94
	$a_phase2 = $config['ipsec']['phase2'];
95
	$a_client = $config['ipsec']['client'];
96

    
97
	if (!isset($ipseccfg['enable'])) {
98
		mwexec("/sbin/ifconfig enc0 down");
99

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

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

    
108
		/* wait for racoon process to die */
109
		sleep(2);
110

    
111
		/* flush SPD and SAD */
112
		mwexec("/usr/local/sbin/setkey -F");
113
		mwexec("/usr/local/sbin/setkey -FP");
114

    
115
		/* disallow IPSEC, it is off */
116
		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
117

    
118
		return true;
119
	} else {
120
		mwexec("/sbin/ifconfig enc0 up");
121
		mwexec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
122

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

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

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

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

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

    
144
				$ep = ipsec_get_phase1_src($ph1ent);
145
				if (!$ep)
146
					continue;
147

    
148
				if(!in_array($ep,$ipmap))
149
					$ipmap[] = $ep;
150

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

    
154
				if (isset ($ph1ent['mobile']))
155
					continue;
156

    
157
				$rg = $ph1ent['remote-gateway'];
158

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

    
167
				$rgmap[$ph1ent['remote-gateway']] = $rg;
168

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

    
173
					$ikeid = $ph2ent['ikeid'];
174

    
175
					if (isset($ph2ent['disabled']))
176
						continue;
177

    
178
					if ($ikeid != $ph1ent['ikeid'])
179
						continue;
180

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

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

    
234
		$pskconf = "";
235

    
236
		if (is_array($a_phase1) && count($a_phase1)) {
237
			foreach ($a_phase1 as $ph1ent) {
238

    
239
				if (isset($ph1ent['disabled']))
240
					continue;
241

    
242
				if (strstr($ph1ent['authentication_method'],'rsa'))
243
					continue;
244

    
245
				$peerid_type = $ph1ent['peerid_type'];
246

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

    
253
					case "address";
254
						$peerid_data = $ph1ent['peerid_data'];
255
						break;
256

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

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

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

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

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

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

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

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

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

    
315
				$racoonconf .= "\nmode_cfg\n";
316
				$racoonconf .= "{\n";
317

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

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

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

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

    
335
				if (isset($a_client['net_list'])) {
336

    
337
					$net_list = '';
338

    
339
					foreach ($a_phase2 as $ph2ent) {
340

    
341
						if (isset($ph2ent['disabled']))
342
							continue;
343

    
344
						if (!isset($ph2ent['mobile']))
345
							continue;
346

    
347
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
348

    
349
						if ($net_list)
350
							$net_list .= ", ";
351
						$net_list .= $localid;
352
					}
353

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

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

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

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

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

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

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

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

    
394
				if (isset($a_client['save_passwd']))
395
					$racoonconf .= "\tsave_passwd on;\n";
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 = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $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 = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $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
						$ca = lookup_ca($ph1ent['caref']);
542
						if ($ca) {
543
							$cafile = "ca-".$ikeid.".crt";
544
							$capath = $g['varetc_path']."/".$cafile;
545

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

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

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

    
558
					}
559

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

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

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

    
577
					/* add remote section to configuration */
578

    
579
					$racoonconf .=<<<EOD
580

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

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

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

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

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

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

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

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

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

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

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

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

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

    
663
					} else {
664
						$rgip = $rgmap[$ph1ent['remote-gateway']];
665

    
666
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
667
							($ph1ent['authentication_method'] == "pre_shared_key"))
668
							&& isset($ph1ent['mobile']))
669
							$localid_spec = " ";
670
						else {
671
							$localid_data = ipsec_get_phase1_src($ph1ent);
672
							if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
673
							$localid_spec = "address {$localid_data}";
674
						}
675
						if (!isset($ph2ent['mobile'])) {
676
							$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
677
							if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
678
							$remoteid_spec = "address {$remoteid_data}";
679
						} else
680
							$remoteid_spec = "anonymous";
681
					}
682

    
683
					if($ph2ent['protocol'] == 'esp') {
684

    
685
						$ealgos = '';
686

    
687
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
688

    
689
							$ealg_id = $ealg['name'];
690
							$ealg_kl = $ealg['keylen'];
691

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

    
727
						$ealgosline = "encryption_algorithm {$ealgos};";
728

    
729
					} else {
730

    
731
						$ealgosline = "encryption_algorithm null_enc;";
732
					}
733

    
734
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
735
					$halgosline = "authentication_algorithm {$halgos};";
736

    
737
					$pfsline = '';
738
					if ($ph2ent['pfsgroup'])
739
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
740
					if (isset($a_client['pfs_group'])) {
741
						$pfsline = '';
742
						if ($a_client['pfs_group'])
743
							$pfsline = "pfs_group {$a_client['pfs_group']};";
744
					}
745

    
746
					$lifeline = '';
747
					if ($ph2ent['lifetime'])
748
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
749

    
750
					/* add sainfo section to configuration */
751
					
752
					$racoonconf .=<<<EOD
753
					
754
sainfo {$localid_spec} {$remoteid_spec}
755
{
756
	remoteid {$ikeid};
757
	{$ealgosline}
758
	{$halgosline}
759
	{$pfsline}
760
	{$lifeline}
761
	compression_algorithm deflate;
762
}
763

    
764
EOD;
765
				}
766
				/* end sainfo */
767
			}
768
			/* end sainfo sections */
769

    
770
			fwrite($fd, $racoonconf);
771
			fclose($fd);
772
		}
773
		/* end racoon.conf */
774

    
775
		/* generate IPsec policies */
776
		if (is_array($a_phase2) && count($a_phase2)) {
777
			/* generate spd.conf */
778
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
779
			if (!$fd) {
780
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
781
				return 1;
782
			}
783

    
784
			$spdconf = "";
785

    
786
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
787
			if ($config['interfaces']['lan']) {
788
				$lanip = get_interface_ip("lan");
789
				if (!empty($lanip) && is_ipaddr($lanip)) {
790
					$lansn = get_interface_subnet("lan");
791
					$lansa = gen_subnet($lanip, $lansn);
792
					$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
793
					$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
794
				}
795
			}
796

    
797
			foreach ($a_phase2 as $ph2ent) {
798

    
799
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
800
					continue;
801

    
802
				if (isset($ph1ent['mobile']))
803
					continue;
804

    
805
				if (isset($ph1ent['disabled']))
806
					continue;
807

    
808
				if (isset($ph2ent['disabled']))
809
					continue;
810

    
811
				$ep = ipsec_get_phase1_src($ph1ent);
812
				if (!$ep)
813
					continue;
814

    
815
				$rgip = $rgmap[$ph1ent['remote-gateway']];
816

    
817
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
818
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
819

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

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

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

    
828
				} else {
829

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

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

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

    
839
				}
840

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

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

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

    
876
		/* needed for racoonctl admin socket */
877
		if (!is_dir("/var/db/racoon"))
878
			mkdir("/var/db/racoon/");
879
		
880
		/* mange racoon process */
881
		if (is_process_running("racoon")) {
882
			sleep("0.1");
883
			/* XXX: This seems to not work in ipsec-tools 0.7.3 but a HUP signal is equivalent. */
884
			//mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
885
			sigkillbypid("{$g['varrun_path']}/racoon.pid", "HUP");
886
			/* load SPD without flushing to be safe on config additions or changes. */
887
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
888
		} else {
889
			/* flush SA + SPD entries */
890
			mwexec("/usr/local/sbin/setkey -FP", false);
891
 			sleep("0.1");
892
			mwexec("/usr/local/sbin/setkey -F", false);
893
 			sleep("0.1");
894
 			/* start racoon */
895
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
896
 			sleep("0.1");
897
 			/* load SPD */
898
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
899

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

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

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

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

    
922
	return 0;
923
}
924

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

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

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

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

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

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

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

    
955
}
956

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

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

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

    
969
function vpn_netgraph_support() {
970
	$iflist = get_configured_interface_list();
971
	foreach ($iflist as $iface) {
972
		$realif = get_real_interface($iface);
973
		/* Get support for netgraph(4) from the nic */
974
		$ifinfo = pfSense_get_interface_addresses($realif);
975
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
976
                	pfSense_ngctl_attach(".", $realif);
977
	}
978
}
979

    
980
function vpn_pptpd_configure() {
981
	global $config, $g;
982

    
983
	$syscfg = $config['system'];
984
	$pptpdcfg = $config['pptpd'];
985

    
986
	if ($g['booting']) {
987
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
988
			return 0;
989

    
990
		echo "Configuring PPTP VPN service... ";
991
	} else {
992
		/* kill mpd */
993
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
994

    
995
		/* wait for process to die */
996
		sleep(3);
997

    
998
		if (is_process_running("mpd -b")) {
999
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1000
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
1001
		}
1002

    
1003
		/* remove mpd.conf, if it exists */
1004
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1005
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1006
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1007
	}
1008

    
1009
	/* make sure pptp-vpn directory exists */
1010
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1011
		mkdir("{$g['varetc_path']}/pptp-vpn");
1012

    
1013
	switch ($pptpdcfg['mode']) {
1014
		case 'server' :
1015
			/* write mpd.conf */
1016
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1017
			if (!$fd) {
1018
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
1019
				return 1;
1020
			}
1021

    
1022
			$mpdconf = <<<EOD
1023
pptps:
1024

    
1025
EOD;
1026

    
1027
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1028
				$mpdconf .= "	load pt{$i}\n";
1029
			}
1030

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

    
1033
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1034

    
1035
				$mpdconf .= <<<EOD
1036

    
1037
pt{$i}:
1038
	new -i pptpd{$i} pt{$i} pt{$i}
1039
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1040
	load pts
1041

    
1042
EOD;
1043
			}
1044

    
1045
			$mpdconf .=<<<EOD
1046

    
1047
pts:
1048
	set iface disable on-demand
1049
	set iface enable proxy-arp
1050
	set iface enable tcpmssfix
1051
	set iface idle 1800
1052
	set iface up-script /usr/local/sbin/vpn-linkup
1053
	set iface down-script /usr/local/sbin/vpn-linkdown
1054
	set bundle enable multilink
1055
	set bundle enable crypt-reqd
1056
	set link yes acfcomp protocomp
1057
	set link no pap chap
1058
	set link enable chap-msv2
1059
	set link mtu 1460
1060
	set link keep-alive 10 60
1061
	set ipcp yes vjcomp
1062
	set bundle enable compression
1063
	set ccp yes mppc
1064
	set ccp yes mpp-e128
1065
	set ccp yes mpp-stateless
1066

    
1067
EOD;
1068

    
1069
			if (!isset ($pptpdcfg['req128'])) {
1070
				$mpdconf .=<<<EOD
1071
	set ccp yes mpp-e40
1072
	set ccp yes mpp-e56
1073

    
1074
EOD;
1075
			}
1076

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

    
1080
			if (!empty($pptpdcfg['dns1'])) {
1081
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1082
				if (!empty($pptpdcfg['dns2']))
1083
					$mpdconf .= " " . $pptpdcfg['dns2'];
1084
				$mpdconf .= "\n";
1085
			} elseif (isset ($config['dnsmasq']['enable'])) {
1086
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1087
				if ($syscfg['dnsserver'][0])
1088
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1089
				$mpdconf .= "\n";
1090
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1091
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1092
			}
1093

    
1094
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1095
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1096
				$acctport = $authport + 1;
1097
				$mpdconf .=<<<EOD
1098
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1099

    
1100
EOD;
1101
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1102
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1103
				$acctport = $authport + 1;
1104
				$mpdconf .=<<<EOD
1105
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1106

    
1107
EOD;
1108
			}
1109
			$mpdconf .=<<<EOD
1110
	set radius retries 3
1111
	set radius timeout 10
1112
	set auth enable radius-auth
1113

    
1114
EOD;
1115

    
1116
				if (isset ($pptpdcfg['radius']['accounting'])) {
1117
					$mpdconf .=<<<EOD
1118
	set auth enable radius-acct
1119
	set radius acct-update 300
1120

    
1121
EOD;
1122
				}
1123
			}
1124

    
1125
			fwrite($fd, $mpdconf);
1126
			fclose($fd);
1127

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

    
1135
			$mpdlinks = "";
1136

    
1137
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1138
				$mpdlinks .=<<<EOD
1139

    
1140
pt{$i}:
1141
	set link type pptp
1142
	set pptp enable incoming
1143
	set pptp disable originate
1144
	set pptp disable windowing
1145

    
1146
EOD;
1147
			}
1148

    
1149
			fwrite($fd, $mpdlinks);
1150
			fclose($fd);
1151

    
1152
			/* write mpd.secret */
1153
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1154
			if (!$fd) {
1155
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
1156
				return 1;
1157
			}
1158

    
1159
			$mpdsecret = "";
1160

    
1161
			if (is_array($pptpdcfg['user'])) {
1162
				foreach ($pptpdcfg['user'] as $user)
1163
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1164
			}
1165

    
1166
			fwrite($fd, $mpdsecret);
1167
			fclose($fd);
1168
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1169

    
1170
			vpn_netgraph_support();
1171

    
1172
			/* fire up mpd */
1173
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/pptp-vpn -p {$g['varrun_path']}/pptp-vpn.pid -s pptps pptps");
1174

    
1175
			break;
1176

    
1177
		case 'redir' :
1178
			break;
1179
	}
1180

    
1181
	if ($g['booting'])
1182
		echo "done\n";
1183

    
1184
	return 0;
1185
}
1186

    
1187
function vpn_pppoes_configure() {
1188
	global $config;
1189

    
1190
	if (is_array($config['pppoes']['pppoe'])) {
1191
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1192
			vpn_pppoe_configure($pppoe);
1193
	}
1194
}
1195

    
1196
function vpn_pppoe_configure(&$pppoecfg) {
1197
	global $config, $g;
1198

    
1199
	$syscfg = $config['system'];
1200

    
1201
	/* create directory if it does not exist */
1202
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1203
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1204

    
1205
	if ($g['booting']) {
1206
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1207
			return 0;
1208

    
1209
		echo "Configuring PPPoE VPN service... ";
1210
	} else {
1211
		/* kill mpd */
1212
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1213

    
1214
		/* wait for process to die */
1215
		sleep(2);
1216

    
1217
	}
1218

    
1219
	switch ($pppoecfg['mode']) {
1220

    
1221
		case 'server' :
1222

    
1223
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1224

    
1225
			if ($pppoecfg['paporchap'] == "chap")
1226
				$paporchap = "set link enable chap";
1227
			else
1228
				$paporchap = "set link enable pap";
1229

    
1230
			/* write mpd.conf */
1231
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1232
			if (!$fd) {
1233
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1234
				return 1;
1235
			}
1236
			$mpdconf = "\n\n";
1237
			$mpdconf .= "poes:\n";
1238

    
1239
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1240
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1241
			}
1242

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

    
1245
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1246

    
1247
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['server']['enable'])) {
1248
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1249
				} else {
1250
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1251
				}
1252

    
1253
				$mpdconf .=<<<EOD
1254

    
1255
poes{$pppoecfg['pppoeid']}{$i}:
1256
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1257
	{$isssue_ip_type}
1258
	load pppoe_standard
1259

    
1260
EOD;
1261
			}
1262

    
1263
			$mpdconf .=<<<EOD
1264

    
1265
pppoe_standard:
1266
	set bundle no multilink
1267
	set bundle enable compression
1268
	set auth max-logins 1
1269
	set iface up-script /usr/local/sbin/vpn-linkup
1270
	set iface down-script /usr/local/sbin/vpn-linkdown
1271
	set iface idle 0
1272
	set iface disable on-demand
1273
	set iface disable proxy-arp
1274
	set iface enable tcpmssfix
1275
	set iface mtu 1500
1276
	set link no pap chap
1277
	{$paporchap}
1278
	set link keep-alive 60 180
1279
	set ipcp yes vjcomp
1280
	set ipcp no vjcomp
1281
	set link max-redial -1
1282
	set link mtu 1492
1283
	set link mru 1492
1284
	set ccp yes mpp-e40
1285
	set ccp yes mpp-e128
1286
	set ccp yes mpp-stateless
1287
	set link latency 1
1288
	#set ipcp dns 10.10.1.3
1289
	#set bundle accept encryption
1290

    
1291
EOD;
1292

    
1293
			if (!empty($pppoecfg['dns1'])) {
1294
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1295
				if (!empty($pppoecfg['dns2']))
1296
					$mpdconf .= " " . $pppoecfg['dns2'];
1297
				$mpdconf .= "\n";
1298
			} elseif (isset ($config['dnsmasq']['enable'])) {
1299
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1300
				if ($syscfg['dnsserver'][0])
1301
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1302
				$mpdconf .= "\n";
1303
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1304
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1305
			}
1306

    
1307
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1308
				$radiusport = "";
1309
				$radiusacctport = "";
1310
				if (isset($pppoecfg['radius']['server']['port']))
1311
					$radiusport = $pppoecfg['radius']['server']['port'];
1312
				if (isset($pppoecfg['radius']['server']['acctport']))
1313
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1314
				$mpdconf .=<<<EOD
1315
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']} {$radiusport} {$radiusacctport}" 
1316
	set radius retries 3
1317
	set radius timeout 10
1318
	set auth enable radius-auth
1319

    
1320
EOD;
1321

    
1322
				if (isset ($pppoecfg['radius']['accounting'])) {
1323
					$mpdconf .=<<<EOD
1324
	set auth enable radius-acct
1325

    
1326
EOD;
1327
				}
1328
			}
1329

    
1330
			fwrite($fd, $mpdconf);
1331
			fclose($fd);
1332

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

    
1340
			$mpdlinks = "";
1341

    
1342
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1343
				$mpdlinks .=<<<EOD
1344
			
1345
poes{$pppoecfg['pppoeid']}{$i}:
1346
	set phys type pppoe
1347
        set pppoe iface {$pppoe_interface}
1348
        set pppoe service "*"
1349
        set pppoe disable originate
1350
        set pppoe enable incoming
1351

    
1352
EOD;
1353
			}
1354

    
1355
			fwrite($fd, $mpdlinks);
1356
			fclose($fd);
1357

    
1358
			if ($pppoecfg['username']) {
1359
				/* write mpd.secret */
1360
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1361
				if (!$fd) {
1362
					printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1363
					return 1;
1364
				}
1365

    
1366
				$mpdsecret = "\n\n";
1367

    
1368
				if (!empty($pppoecfg['username'])) {
1369
					$item = explode(" ", $pppoecfg['username']);
1370
					foreach($item as $userdata) {
1371
						$data = explode(":", $userdata);
1372
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1373
					}
1374
				}
1375

    
1376
				fwrite($fd, $mpdsecret);
1377
				fclose($fd);
1378
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1379
			}
1380

    
1381
			/* Get support for netgraph(4) from the nic */
1382
			pfSense_ngctl_attach(".", $pppoe_interface);
1383
			/* fire up mpd */
1384
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn -p {$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid -s poes poes");
1385

    
1386
			break;
1387
	}
1388

    
1389
	if ($g['booting'])
1390
		echo "done\n";
1391

    
1392
	return 0;
1393
}
1394

    
1395
function vpn_l2tp_configure() {
1396
	global $config, $g;
1397

    
1398
	$syscfg = $config['system'];
1399
	$l2tpcfg = $config['l2tp'];
1400

    
1401
	/* create directory if it does not exist */
1402
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1403
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1404

    
1405
	if ($g['booting']) {
1406
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1407
			return 0;
1408

    
1409
		echo "Configuring l2tp VPN service... ";
1410
	} else {
1411
		/* kill mpd */
1412
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1413

    
1414
		/* wait for process to die */
1415
		sleep(8);
1416

    
1417
	}
1418

    
1419
	/* make sure l2tp-vpn directory exists */
1420
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1421
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1422

    
1423
	switch ($l2tpcfg['mode']) {
1424

    
1425
		case 'server' :
1426
			if ($l2tpcfg['paporchap'] == "chap")
1427
				$paporchap = "set link enable chap";
1428
			else
1429
				$paporchap = "set link enable pap";
1430

    
1431
			/* write mpd.conf */
1432
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1433
			if (!$fd) {
1434
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1435
				return 1;
1436
			}
1437
			$mpdconf = "\n\n";
1438
			$mpdconf .=<<<EOD
1439
l2tps:
1440

    
1441
EOD;
1442

    
1443
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1444
				$mpdconf .= "	load l2tp{$i}\n";
1445
			}
1446

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

    
1449
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1450

    
1451
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1452
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1453
				} else {
1454
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1455
				}
1456

    
1457
				$mpdconf .=<<<EOD
1458

    
1459
l2tp{$i}:
1460
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1461
	{$isssue_ip_type}
1462
	load l2tp_standard
1463

    
1464
EOD;
1465
			}
1466

    
1467
			$mpdconf .=<<<EOD
1468

    
1469
l2tp_standard:
1470
        set bundle disable multilink
1471
        set bundle enable compression
1472
        set bundle yes crypt-reqd
1473
        set ipcp yes vjcomp
1474
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1475
        set ccp yes mppc
1476
        set iface disable on-demand
1477
        set iface enable proxy-arp
1478
	set iface up-script /usr/local/sbin/vpn-linkup
1479
	set iface down-script /usr/local/sbin/vpn-linkdown
1480
        set link yes acfcomp protocomp
1481
        set link no pap chap
1482
        set link enable chap
1483
        set link keep-alive 10 180
1484

    
1485
EOD;
1486

    
1487
			if (!empty($l2tpcfg['dns1'])) {
1488
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1489
				if (!empty($l2tpcfg['dns2']))
1490
					$mpdconf .= " " . $l2tpcfg['dns2'];
1491
				$mpdconf .= "\n";
1492
			} elseif (isset ($config['dnsmasq']['enable'])) {
1493
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1494
				if ($syscfg['dnsserver'][0])
1495
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1496
				$mpdconf .= "\n";
1497
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1498
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1499
			}
1500

    
1501
			if (isset ($l2tpcfg['radius']['enable'])) {
1502
				$mpdconf .=<<<EOD
1503
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1504
	set radius retries 3
1505
	set radius timeout 10
1506
	set auth enable radius-auth
1507

    
1508
EOD;
1509

    
1510
				if (isset ($l2tpcfg['radius']['accounting'])) {
1511
					$mpdconf .=<<<EOD
1512
	set auth enable radius-acct
1513

    
1514
EOD;
1515
				}
1516
			}
1517

    
1518
			fwrite($fd, $mpdconf);
1519
			fclose($fd);
1520

    
1521
			/* write mpd.links */
1522
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1523
			if (!$fd) {
1524
				printf("Error: cannot open mpd.links in vpn_l2tp_configure().\n");
1525
				return 1;
1526
			}
1527

    
1528
			$mpdlinks = "";
1529

    
1530
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1531
				$mpdlinks .=<<<EOD
1532

    
1533
l2tp{$i}:
1534
	set link type l2tp
1535
        set l2tp enable incoming
1536
        set l2tp disable originate
1537

    
1538
EOD;
1539
			if (!empty($l2tpcfg['secret']))
1540
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1541
			}
1542

    
1543
			fwrite($fd, $mpdlinks);
1544
			fclose($fd);
1545

    
1546
			/* write mpd.secret */
1547
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1548
			if (!$fd) {
1549
				printf("Error: cannot open mpd.secret in vpn_l2tp_configure().\n");
1550
				return 1;
1551
			}
1552

    
1553
			$mpdsecret = "\n\n";
1554

    
1555
			if (is_array($l2tpcfg['user'])) {
1556
				foreach ($l2tpcfg['user'] as $user)
1557
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1558
			}
1559

    
1560
			fwrite($fd, $mpdsecret);
1561
			fclose($fd);
1562
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1563

    
1564
			vpn_netgraph_support();
1565

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

    
1569
			break;
1570

    
1571
		case 'redir' :
1572
			break;
1573
	}
1574

    
1575
	if ($g['booting'])
1576
		echo "done\n";
1577

    
1578
	return 0;
1579
}
1580

    
1581
/* Walk the tunnels for hostname endpoints. If the hostnames 
1582
 * resolve to a different IP now compared to the DNS cache
1583
 * we reload the policies if the endpoint has changed */
1584
function vpn_ipsec_refresh_policies() {
1585
	global $config;
1586
	global $g;
1587

    
1588
	$ipseccfg = $config['ipsec'];
1589
	$a_phase1 = $config['ipsec']['phase1'];
1590
	$a_phase2 = $config['ipsec']['phase2'];
1591

    
1592
	if (isset($ipseccfg['disable'])) {
1593
		return true;
1594
	}
1595

    
1596
	/* Walk the Ipsec tunnel array */
1597
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1598
		return;
1599
	}
1600

    
1601
	foreach ($a_phase1 as $phase1) {
1602
		if (isset($phase1['disabled'])) {
1603
			continue;
1604
		}
1605
		if (is_ipaddr($phase1['remote-gateway'])) {
1606
			continue;
1607
		}
1608
		if (!is_ipaddr($phase1['remote-gateway'])) {
1609
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1610
			$dnscache = trim($dnscache);
1611
			/* we should have the old IP addresses in the dnscache now */
1612
			if($dnscache <> "") {
1613
				$oldphase1 = $phase1;
1614
				$oldphase1['remote-gateway'] = trim($dnscache);
1615
				/* now we need to find all tunnels for this host */
1616
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1617
					continue;
1618
				}
1619
				foreach ($a_phase2 as $phase2) {
1620
					if($phase2['ikeid'] == $phase1['ikeid']) {
1621
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1622
					}
1623
				}
1624
			}
1625
		}
1626
	}
1627

    
1628
	/* process all generated spd.conf files from tmp which are left behind
1629
	 * behind by either changes of dynamic tunnels or manual edits
1630
	 * scandir() is only available in PHP5 */
1631
	$tmpfiles = array();
1632
	$dh  = opendir($g['tmp_path']);
1633
	while (false !== ($filename = readdir($dh))) {
1634
		if(preg_match("/^spd.conf.reload./", $filename)) {
1635
			$tmpfiles[] = $filename;
1636
		}
1637
	}
1638
	sort($tmpfiles);
1639
	foreach($tmpfiles as $tmpfile) {
1640
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1641
		if($ret == 0) {
1642
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1643
		} else {
1644
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1645
		}
1646
	}
1647
}
1648

    
1649
/* reloads the tunnel configuration for a tunnel item
1650
 * Will remove and add SPD polices */
1651
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1652
	global $config;
1653
	global $g;
1654

    
1655
	/* if we are not passed a old tunnel array we create one */
1656
	if(empty($old_phase1)) {
1657
		$old_phase1 = $phase1;
1658
	}
1659
	if(empty($old_phase2)) {
1660
		$old_phase2 = $phase2;
1661
	}
1662

    
1663
	$sad_arr = ipsec_dump_sad();
1664

    
1665
	$ep = ipsec_get_phase1_src($phase1);
1666
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1667
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1668

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

    
1672
	$old_ep = ipsec_get_phase1_src($old_phase1);
1673
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1674
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1675

    
1676
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1677
	 * try to resolve it now and add it to the list for dnswatch */
1678
	if (!is_ipaddr($phase1['remote-gateway'])) {
1679
		$rgip = resolve_retry($phase1['remote-gateway']);
1680
		add_hostname_to_watch($phase1['remote-gateway']);
1681
		if (!$rgip) {
1682
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1683
			return false;
1684
		}
1685
	} else {
1686
		$rgip = $phase1['remote-gateway'];
1687
	}
1688
	if (!$ep) {
1689
		log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1690
		return false;
1691
	}
1692

    
1693
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1694
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1695
	}
1696
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1697
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1698
	}
1699

    
1700
	$spdconf = "";
1701
	/* Delete old SPD policies if there are changes between the old and new */
1702
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1703
		$spdconf .= "spddelete {$old_local_subnet} " .
1704
			"{$old_remote_subnet} any -P out ipsec " .
1705
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1706
			"{$old_gw}/unique;\n";
1707
		$spdconf .= "spddelete {$old_remote_subnet} " .
1708
			"{$old_local_subnet} any -P in ipsec " .
1709
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1710
			"{$old_ep}/unique;\n";
1711

    
1712
		/* zap any existing SA entries */
1713
		foreach($sad_arr as $sad) {
1714
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1715
				$spdconf .= "delete {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1716
			}
1717
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1718
				$spdconf .= "delete {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1719
			}
1720
		}
1721
	}
1722

    
1723
	/* Create new SPD entries for the new configuration */
1724
	/* zap any existing SA entries beforehand */
1725
	foreach($sad_arr as $sad) {
1726
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1727
			$spdconf .= "delete {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1728
		}
1729
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1730
			$spdconf .= "delete {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1731
		}
1732
	}
1733
	/* add new SPD policies to replace them */
1734
	$spdconf .= "spdadd {$local_subnet} " .
1735
		"{$remote_subnet} any -P out ipsec " .
1736
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1737
		"{$rgip}/unique;\n";
1738
	$spdconf .= "spdadd {$remote_subnet} " .
1739
		"{$local_subnet} any -P in ipsec " .
1740
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1741
		"{$ep}/unique;\n";
1742

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

    
1745
	$now = time();
1746
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1747
	/* generate temporary spd.conf */
1748
	file_put_contents($spdfile, $spdconf);
1749
	return true;
1750
}
1751

    
1752
function vpn_ipsec_configure_preferoldsa() {
1753
	global $config;
1754
	if(isset($config['ipsec']['preferoldsa']))
1755
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1756
	else
1757
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1758
}
1759

    
1760
?>
(52-52/61)