Project

General

Profile

Download (54.9 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	/sbin/route	/bin/mkdir
39
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/racoonctl	/usr/local/sbin/racoon
40
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/filterdns	/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
	if ($g['platform'] == 'jail')
86
		return;
87
	/* get the automatic ping_hosts.sh ready */
88
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
89
	touch("{$g['vardb_path']}/ipsecpinghosts");
90

    
91
	vpn_ipsec_configure_preferoldsa();
92

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

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

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

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

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

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

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

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

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

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

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

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

    
144
				$ep = ipsec_get_phase1_src($ph1ent);
145
				if (!is_ipaddr($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 filterdns */
153

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

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

    
159
				if (!is_ipaddr($rg)) {
160
					$filterdns_list[] = "{$rg}";
161
					add_hostname_to_watch($rg);
162
					if(! $g['booting'])
163
						$rg = resolve_retry($rg);
164
					if (!is_ipaddr($rg))
165
						continue;
166
				}
167
				if(array_search($rg, $rgmap)) {
168
					log_error("The remote gateway {$rg} already exists on another phase 1 entry");
169
					continue;
170
				}
171
				$rgmap[$ph1ent['remote-gateway']] = $rg;
172

    
173
				if (is_array($a_phase2)) {
174
					/* step through each phase2 entry */
175
					foreach ($a_phase2 as $ph2ent) {
176
						$ikeid = $ph2ent['ikeid'];
177

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

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

    
184
						$ph2ent['localid']['mode'] = $ph2ent['mode'];
185
						/* add an ipsec pinghosts entry */
186
						if ($ph2ent['pinghost']) {
187
							$iflist = get_configured_interface_list();
188
							foreach ($iflist as $ifent => $ifname) {
189
								if(is_ipaddrv6($ph2ent['pinghost'])) {
190
									$interface_ip = get_interface_ipv6($ifent);
191
									if(!is_ipaddrv6($interface_ip))
192
										continue;
193
									$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
194
									if (ip_in_subnet($interface_ip, $local_subnet)) {
195
										$srcip = $interface_ip;
196
										break;
197
									}
198
								} else {
199
									$interface_ip = get_interface_ip($ifent);
200
									if(!is_ipaddrv4($interface_ip))
201
										continue;
202
									$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
203
									if (ip_in_subnet($interface_ip, $local_subnet)) {
204
										$srcip = $interface_ip;
205
										break;
206
									}
207
								}
208
							}
209
							$dstip = $ph2ent['pinghost'];
210
							if(is_ipaddrv6($dstip)) {
211
								$family = "inet6";
212
							} else {
213
								$family = "inet";
214
							}
215
							if (is_ipaddr($srcip))
216
								$ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n";
217
						}
218
					}
219
					file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts);
220
				}
221
			}
222
		}
223

    
224
		/* generate CA certificates files */
225
		if (is_array($config['ca']) && count($config['ca'])) {
226
			foreach ($config['ca'] as $ca) {
227
				if (!isset($ca['crt'])) {
228
					log_error(sprintf(gettext("Error: Invalid certificate info for %s"), $ca['descr']));
229
					continue;
230
				}
231
				$cert = base64_decode($ca['crt']);
232
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
233
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
234
					log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $ca['descr']));
235
					continue;
236
				}
237
				$fname = $g['varetc_path']."/".$x509cert['hash'].".0";
238
				if (!file_put_contents($fname, $cert)) {
239
					log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $ca['descr']));
240
					continue;
241
				}
242
			}
243
		}
244
		
245
		/* generate psk.txt */
246
		$fd = fopen("{$g['varetc_path']}/psk.txt", "w");
247
		if (!$fd) {
248
			printf(gettext("Error: cannot open psk.txt in vpn_ipsec_configure().") . "\n");
249
			return 1;
250
		}
251

    
252
		$pskconf = "";
253

    
254
		if (is_array($a_phase1) && count($a_phase1)) {
255
			foreach ($a_phase1 as $ph1ent) {
256

    
257
				if (isset($ph1ent['disabled']))
258
					continue;
259

    
260
				if (strstr($ph1ent['authentication_method'],'rsa'))
261
					continue;
262

    
263
				$peerid_type = $ph1ent['peerid_type'];
264

    
265
				switch ($peerid_type) {
266
					case "peeraddress":
267
						$peerid_type = "address";
268
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
269
						break;
270

    
271
					case "address";
272
						$peerid_data = $ph1ent['peerid_data'];
273
						break;
274

    
275
					case "fqdn";
276
					case "keyid tag";
277
					case "user_fqdn";
278
						$peerid_data = $ph1ent['peerid_data'];
279
						break;
280
				}
281

    
282
				if (!empty($peerid_data) && !empty($ph1ent['pre-shared-key']))
283
					$pskconf .= trim($peerid_data) . "\t" . trim($ph1ent['pre-shared-key']) . "\n";
284
			}
285
		}
286

    
287
		/* Add user PSKs */
288
		foreach ($config['system']['user'] as $user) {
289
			if (!empty($user['ipsecpsk'])) {
290
				$pskconf .= "{$user['name']}\t{$user['ipsecpsk']}\n";
291
			}
292
		}
293

    
294
		/* add PSKs for mobile clients */
295
		if (is_array($ipseccfg['mobilekey'])) {
296
			foreach ($ipseccfg['mobilekey'] as $key) {
297
				$pskconf .= "{$key['ident']}\t{$key['pre-shared-key']}\n";
298
			}
299
		}
300

    
301
		fwrite($fd, $pskconf);
302
		fclose($fd);
303
		chmod("{$g['varetc_path']}/psk.txt", 0600);
304
			
305
		/* begin racoon.conf */
306
		if ((is_array($a_phase1) && count($a_phase1)) ||
307
			(is_array($a_phase2) && count($a_phase2))) {
308

    
309
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
310
			if (!$fd) {
311
				printf(gettext("Error: cannot open racoon.conf in vpn_ipsec_configure().") . "\n");
312
				return 1;
313
			}
314

    
315
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
316
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
317
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
318

    
319
			/* begin listen section */
320
			if (count($ipmap)) {
321
				$racoonconf .= "\nlisten\n";
322
				$racoonconf .= "{\n";
323
				$racoonconf .= "	adminsock \"/var/db/racoon/racoon.sock\" \"root\" \"wheel\" 0660;\n";
324
				foreach ($ipmap as $addr) {
325
					$racoonconf .= "\tisakmp {$addr} [500];\n";
326
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
327
				}
328
				$racoonconf .= "}\n\n";
329
			}
330

    
331
			/* begin mode_cfg section */
332
			if (is_array($a_client) && isset($a_client['enable'])) {
333

    
334
				$racoonconf .= "\nmode_cfg\n";
335
				$racoonconf .= "{\n";
336

    
337
				if ($a_client['user_source'])
338
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
339
				if ($a_client['group_source'])
340
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
341

    
342
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
343
					$pool_address = $a_client['pool_address'];
344
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
345

    
346
					$pool_address = long2ip32(ip2long($pool_address)+1);
347
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
348

    
349
					$racoonconf .= "\tpool_size {$pool_size};\n";
350
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
351
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
352
				}
353

    
354
				if (isset($a_client['net_list'])) {
355

    
356
					$net_list = '';
357

    
358
					foreach ($a_phase2 as $ph2ent) {
359

    
360
						if (isset($ph2ent['disabled']))
361
							continue;
362

    
363
						if (!isset($ph2ent['mobile']))
364
							continue;
365

    
366
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
367

    
368
						if ($net_list)
369
							$net_list .= ", ";
370
						$net_list .= $localid;
371
					}
372

    
373
					if ($net_list)
374
						$racoonconf .= "\tsplit_network include {$net_list};\n";
375
				}
376

    
377
				if ($a_client['dns_server1'])
378
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
379
				if ($a_client['dns_server2'])
380
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
381
				if ($a_client['dns_server3'])
382
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
383
				if ($a_client['dns_server4'])
384
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
385

    
386
				if ($a_client['wins_server1'])
387
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
388
				if ($a_client['wins_server2'])
389
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
390

    
391
				if ($a_client['dns_domain']) {
392
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
393
					if (empty($a_client['dns_split']))
394
						$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
395
				}
396

    
397
				if ($a_client['dns_split']) {
398
					$domain_array = preg_split("/[ ,]+/",$a_client['dns_split']);
399
					$domain_string = implode('", "', $domain_array);
400
					$racoonconf .= "\tsplit_dns \"{$domain_string}\";\n";
401
				}
402

    
403
				if ($a_client['pfs_group'])
404
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
405

    
406
				if ($a_client['login_banner']) {
407
					$fn = "{$g['varetc_path']}/racoon.motd";
408
					$fd1 = fopen($fn, "w");
409
					if (!$fd1) {
410
						printf(gettext("Error: cannot open server %s in vpn.\n"), $fn);
411
						return 1;
412
					}
413

    
414
					fwrite($fd1, $a_client['login_banner']);
415
					fclose($fd1);
416

    
417
					$racoonconf .= "\tbanner \"{$fn}\";\n";
418
				}
419

    
420
				if (isset($a_client['save_passwd']))
421
					$racoonconf .= "\tsave_passwd on;\n";
422

    
423
				$racoonconf .= "}\n\n";
424
			}
425
			/* end mode_cfg section */
426
			
427
// Disable this for now, when LDAP support returns it will be via external script auth, 
428
//    since we no longer build racoon with LDAP integrated. This is only preventing racoon from running.
429
//
430
//			if ($a_client['user_source'] != "system") {
431
//				if (is_array($config['system']['authserver'])) {
432
//					foreach ($config['system']['authserver'] as $authcfg) {
433
//						if ($authcfg['type'] == 'ldap' and $authcfg['name'] == $a_client['user_source']) 
434
//							$thisauthcfg = $authcfg;
435
//					}
436
//
437
//					/* begin ldapcfg */
438
//					$racoonconf .= "ldapcfg {\n";
439
//					$racoonconf .= "\tversion 3;\n";
440
//					$racoonconf .= "\thost \"".$thisauthcfg['host']."\";\n";
441
//					$lport = "389";
442
//					if ($authcfg['port'] != "")
443
//						$lport = $authcfg['port'];
444
//					$racoonconf .= "\tport ".$lport.";\n";
445
//					$racoonconf .= "\tbase \"".$thisauthcfg['ldap_basedn']."\";\n";
446
//					$racoonconf .= "\tsubtree on;\n";
447
//					$racoonconf .= "\tbind_dn \"".$thisauthcfg['ldap_binddn']."\";\n";
448
//					$racoonconf .= "\tbind_pw \"".$thisauthcfg['ldap_bindpw']."\";\n";
449
//					$racoonconf .= "\tattr_user \"".$thisauthcfg['ldap_attr_user']."\";\n";
450
//					$racoonconf .= "}\n\n";
451
//					/* end ldapcfg */
452
//				}
453
//			}
454

    
455
			/* begin remote sections */
456
			if (is_array($a_phase1) && count($a_phase1)) {
457
				/* begin remote */
458
				foreach ($a_phase1 as $ph1ent) {
459

    
460
					if (isset($ph1ent['disabled']))
461
						continue;
462

    
463
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
464
						continue;
465

    
466
					$ikeid = $ph1ent['ikeid'];
467

    
468
					$ep = ipsec_get_phase1_src($ph1ent);
469
					if (!$ep)
470
						continue;
471

    
472
					if (!isset($ph1ent['mobile'])) {
473
						$rgip = $rgmap[$ph1ent['remote-gateway']];
474
						if (!$rgip)
475
							continue;
476
					}
477

    
478
					$myid_type = $ph1ent['myid_type'];
479

    
480
					switch ($myid_type) {
481

    
482
						case "myaddress":
483
							$myid_type = "address";
484
							$myid_data = $ep;
485
							break;
486

    
487
						case "dyn_dns":
488
							$myid_type = "address";
489
							$myid_data = resolve_retry($ph1ent['myid_data']);
490
							break;
491

    
492
						case "address";
493
							$myid_data = $ph1ent['myid_data'];
494
							break;
495

    
496
						case "fqdn";
497
						case "keyid tag";
498
						case "user_fqdn";
499
						case "asn1dn";
500
							$myid_data = $ph1ent['myid_data'];
501
							if( $myid_data )
502
								$myid_data = "\"".$myid_data."\"";
503
							break;
504
					}
505

    
506
					$peerid_type = $ph1ent['peerid_type'];
507

    
508
					switch ($peerid_type) {
509
						case "peeraddress":
510
							$peerid_type = "address";
511
							$peerid_data = $rgip;
512
							break;
513

    
514
						case "address";
515
							$peerid_data = $ph1ent['peerid_data'];
516
							break;
517

    
518
						case "fqdn";
519
						case "keyid tag";
520
						case "user_fqdn";
521
						case "asn1dn";
522
							$peerid_data = $ph1ent['peerid_data'];
523
							if( $peerid_data )
524
								$peerid_data = "\"".$peerid_data."\"";
525
							break;
526
					}
527

    
528
					$natt = "off";
529
					if (isset($ph1ent['nat_traversal']))
530
						$natt = $ph1ent['nat_traversal'];
531

    
532
					$init = "on";
533
					$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "off";
534
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
535
					$passive = "";
536
					if (isset($ph1ent['mobile'])) {
537
						$rgip = "anonymous";
538
						$passive = "passive on;";
539
						$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
540
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
541
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
542
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "on";
543
						} else {
544
							$init = "off";
545
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "unique";
546
						}
547
					}
548

    
549
					$dpdline1 = '';
550
					$dpdline2 = '';
551
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
552
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
553
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
554
					}
555

    
556
					if (isset ($ph1ent['authentication_method']))
557
						$authmethod = $ph1ent['authentication_method'];
558
					else
559
						$authmethod = 'pre_shared_key';
560

    
561
					$certline = '';
562

    
563
					if (strstr($authmethod,'rsa')) {
564

    
565
						$cert = lookup_cert($ph1ent['certref']);
566

    
567
						if (!$cert)
568
						{
569
							log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
570
							continue;
571
						}
572

    
573
						$certfile = "cert-".$ikeid.".crt";
574
						$certpath = $g['varetc_path']."/".$certfile;
575

    
576
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
577
						{
578
							log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
579
							continue;
580
						}
581

    
582
						chmod($certpath, 0600);
583

    
584
						$keyfile = "cert-".$ikeid.".key";
585
						$keypath = $g['varetc_path']."/".$keyfile;
586

    
587
						if (!file_put_contents($keypath, base64_decode($cert['prv'])))
588
						{
589
							log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
590
							continue;
591
						}
592

    
593
						chmod($keypath, 0600);
594

    
595
						$ca = lookup_ca($ph1ent['caref']);
596
						if ($ca) {
597
							$cafile = "ca-".$ikeid.".crt";
598
							$capath = $g['varetc_path']."/".$cafile;
599

    
600
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
601
							{
602
								log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
603
								continue;
604
							}
605

    
606
							chmod($capath, 0600);
607
							$caline = "ca_type x509 \"".basename($capath)."\";";
608
						}
609

    
610
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
611

    
612
					}
613

    
614
					$ealgos = '';
615
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
616
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
617
					if ($ealg_kl)
618
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
619
					else
620
						$ealgos = $ealgos.$ealg_id;
621

    
622
					$lifeline = '';
623
					if ($ph1ent['lifetime'])
624
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
625

    
626
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
627
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
628
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
629
					}
630

    
631
					/* add remote section to configuration */
632

    
633
					$racoonconf .=<<<EOD
634

    
635
remote {$rgip}
636
{
637
	ph1id {$ikeid};
638
	exchange_mode {$ph1ent['mode']};
639
	my_identifier {$myid_type} {$myid_data};
640
	{$peerid_spec}
641
	ike_frag on;
642
	generate_policy = {$genp};
643
	initial_contact = {$init};
644
	nat_traversal = {$natt};
645
	{$certline}
646
	{$caline}
647
	{$dpdline1}
648
	{$dpdline2}
649
	support_proxy on;
650
	proposal_check {$pcheck};
651
	{$passive}
652

    
653
	proposal
654
	{
655
		authentication_method {$authmethod};
656
		encryption_algorithm ${ealgos};
657
		hash_algorithm {$ph1ent['hash-algorithm']};
658
		dh_group {$ph1ent['dhgroup']};
659
		${lifeline}
660
	}
661
}
662

    
663
EOD;
664
				}
665
				/* end remote */
666
			}
667
			/* end remote sections */
668
		
669
			/* begin sainfo sections */
670
			if (is_array($a_phase2) && count($a_phase2)) {
671

    
672
				/* begin sainfo */
673
				foreach ($a_phase2 as $ph2ent) {
674

    
675
					$ikeid = $ph2ent['ikeid'];
676

    
677
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
678
						continue;
679

    
680
					if (isset($ph1ent['disabled']))
681
						continue;
682

    
683
					if (isset($ph2ent['disabled']))
684
						continue;
685

    
686
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
687
						continue;
688

    
689
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
690

    
691
						$localid_type = $ph2ent['localid']['type'];
692
						$ph2ent['localid']['mode'] = $ph2ent['mode'];
693
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
694
						/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
695
						if (($localid_type == "none") ||
696
							(($ph1ent['authentication_method'] == "xauth_psk_server") ||
697
							($ph1ent['authentication_method'] == "pre_shared_key"))
698
							&& isset($ph1ent['mobile'])
699
							&& (ipsec_get_number_of_phase2($ikeid)==1))
700
							$localid_spec = " ";
701
						else {
702
							if ($localid_type != "address") {
703
								$localid_type = "subnet";
704
							}
705
							// Don't let an empty subnet into racoon.conf, it can cause parse errors. Ticket #2201.
706
							if (!is_ipaddr($localid_data) && !is_subnet($localid_data)) {
707
								log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet.");
708
								continue;
709
							}
710
							$localid_spec = "{$localid_type} {$localid_data} any";
711
							if (!empty($ph2ent['natlocalid'])) {
712
								$natlocalid_data =  ipsec_idinfo_to_cidr($ph2ent['natlocalid']);
713
								if ($ph2ent['natlocalid']['type'] != "address") {
714
									if (is_subnet($natlocalid_data))
715
										$localid_spec .= " nat subnet {$natlocalid_data} any";
716
								} else {
717
									if (is_ipaddr($natlocalid_data))
718
										$localid_spec .= " nat address {$natlocalid_data} any";
719
								}
720
							}
721
						}
722

    
723
						if (!isset($ph2ent['mobile'])) {
724
							$remoteid_type = $ph2ent['remoteid']['type'];
725
							if ($remoteid_type != "address")
726
								$remoteid_type = "subnet";
727

    
728
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
729
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
730
						} else
731
							$remoteid_spec = "anonymous";
732

    
733
					} else {
734
						$rgip = $rgmap[$ph1ent['remote-gateway']];
735

    
736
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
737
							($ph1ent['authentication_method'] == "pre_shared_key"))
738
							&& isset($ph1ent['mobile']))
739
							$localid_spec = " ";
740
						else {
741
							$localid_data = ipsec_get_phase1_src($ph1ent);
742
							if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
743
							$localid_spec = "address {$localid_data}";
744
						}
745
						if (!isset($ph2ent['mobile'])) {
746
							$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
747
							if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
748
							$remoteid_spec = "address {$remoteid_data}";
749
						} else
750
							$remoteid_spec = "anonymous";
751
					}
752

    
753
					if($ph2ent['protocol'] == 'esp') {
754

    
755
						$ealgos = '';
756

    
757
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
758

    
759
							$ealg_id = $ealg['name'];
760
							$ealg_kl = $ealg['keylen'];
761

    
762
							if ($ealg_kl) {
763
								if( $ealg_kl == "auto" ) {
764
									/*   This seems to be required on my system and was not reproducable
765
									 *   on other systems.   For some reason $p2_ealgos is not defined
766
									 *   and needs to be read back in!?  -sullrich Aug 26, 2009 
767
									 */
768
									if(!$p2_ealgos)
769
										require("ipsec.inc");
770
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
771
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
772
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
773
									/* in some cases where include ordering is suspect these variables
774
									   are somehow 0 and we enter this loop forever and timeout after 900
775
									   seconds wrecking bootup */
776
									if($key_hi != 0 and $key_lo !=0 and $key_step !=0) {
777
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
778
//											Uncomment the next line if you want to test the comment 5 lines up.											
779
//											echo "$keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step \n";
780
											if ($ealgos)
781
												$ealgos = $ealgos.", ";
782
											$ealgos = $ealgos.$ealg_id." ".$keylen;
783
										}
784
									}
785
								} else {
786
									if ($ealgos)
787
										$ealgos = $ealgos.", ";
788
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
789
								}
790
							} else {
791
								if ($ealgos)
792
									$ealgos = $ealgos.", ";
793
								$ealgos = $ealgos.$ealg_id;
794
							}
795
						}
796

    
797
						$ealgosline = "encryption_algorithm {$ealgos};";
798

    
799
					} else {
800

    
801
						$ealgosline = "encryption_algorithm null_enc;";
802
					}
803

    
804
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
805
					$halgosline = "authentication_algorithm {$halgos};";
806

    
807
					$pfsline = '';
808
					if ($ph2ent['pfsgroup'])
809
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
810
					if (isset($a_client['pfs_group'])) {
811
						$pfsline = '';
812
						if ($a_client['pfs_group'])
813
							$pfsline = "pfs_group {$a_client['pfs_group']};";
814
					}
815

    
816
					$lifeline = '';
817
					if ($ph2ent['lifetime'])
818
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
819

    
820
					/* add sainfo section to configuration */
821
					
822
					$racoonconf .=<<<EOD
823
					
824
sainfo {$localid_spec} {$remoteid_spec}
825
{
826
	remoteid {$ikeid};
827
	{$ealgosline}
828
	{$halgosline}
829
	{$pfsline}
830
	{$lifeline}
831
	compression_algorithm deflate;
832
}
833

    
834
EOD;
835
				}
836
				/* end sainfo */
837
			}
838
			/* end sainfo sections */
839

    
840
			fwrite($fd, $racoonconf);
841
			fclose($fd);
842
		}
843
		/* end racoon.conf */
844

    
845
		/* generate IPsec policies */
846
		/* generate spd.conf */
847
		$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
848
		if (!$fd) {
849
			printf(gettext("Error: cannot open spd.conf in vpn_ipsec_configure().") . "\n");
850
			return 1;
851
		}
852

    
853
		$spdconf = "";
854
		$natfilterrules = false;
855
		if (is_array($a_phase2) && count($a_phase2)) {
856
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
857
			if ($config['interfaces']['lan']) {
858
				$lanip = get_interface_ip("lan");
859
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
860
					$lansn = get_interface_subnet("lan");
861
					$lansa = gen_subnet($lanip, $lansn);
862
					$spdconf .= "spdadd -4 {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
863
					$spdconf .= "spdadd -4 {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
864
				}
865
				$lanipv6 = get_interface_ipv6("lan");
866
				if (!empty($lanipv6) && is_ipaddrv6($lanipv6)) {
867
					$lansnv6 = get_interface_subnetv6("lan");
868
					$lansav6 = gen_subnetv6($lanipv6, $lansnv6);
869
					$spdconf .= "spdadd -6 {$lanipv6}/128 {$lansav6}/{$lansnv6} any -P out none;\n";
870
					$spdconf .= "spdadd -6 {$lansav6}/{$lansnv6} {$lanipv6}/128 any -P in none;\n";
871
				}
872
			}
873

    
874
			foreach ($a_phase2 as $ph2ent) {
875

    
876
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
877
					continue;
878

    
879
				if (isset($ph1ent['mobile']))
880
					continue;
881

    
882
				if (isset($ph1ent['disabled']))
883
					continue;
884

    
885
				if (isset($ph2ent['disabled']))
886
					continue;
887

    
888
				$ep = ipsec_get_phase1_src($ph1ent);
889
				if (!$ep)
890
					continue;
891

    
892
				$rgip = $rgmap[$ph1ent['remote-gateway']];
893
				if(!is_ipaddr($rgip))
894
					continue;
895

    
896
				$ph2ent['localid']['mode'] = $ph2ent['mode'];
897
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
898
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
899

    
900
				if(($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == 'tunnel6')) {
901
					// Error will be logged above, no need to log this twice. #2201
902
					if (!is_subnet($localid))
903
						continue;
904

    
905
					if($ph2ent['mode'] == "tunnel6")
906
						$family = "-6";
907
					else
908
						$family = "-4";
909

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

    
913
					if (!empty($ph2ent['natlocalid'])) {
914
						$natlocalid = ipsec_idinfo_to_cidr($ph2ent['natlocalid'],true);
915
						$spdconf .= "spdadd {$family} {$remoteid} {$natlocalid} any -P in ipsec " .
916
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
917
						$natfilterrules = true;
918
					} else
919
						$spdconf .= "spdadd {$family} {$remoteid} {$localid} any -P in ipsec " .
920
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
921

    
922
				} else {
923

    
924
					$localid_data = ipsec_get_phase1_src($ph1ent);
925
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
926

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

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

    
933
				}
934

    
935
				/* static route needed? */
936
				if (is_ipaddr($ph1ent['interface'])) {
937
					$vip = find_virtual_ip_alias($ph1ent['interface']);
938
					if (preg_match("/^carp|^[a-z0-9]+_vip/i", $vip['interface']))
939
						$parentinterface = link_carp_interface_to_parent($vip['interface']);
940
					else
941
						$parentinterface = $vip['interface'];
942
				} else if (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
943
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
944
				else
945
					$parentinterface = $ph1ent['interface'];
946

    
947
				if (is_ipaddr($rgip)) {
948
					/* add endpoint routes to correct gateway on interface */
949
					if (interface_has_gateway($parentinterface)) {
950
						$gatewayip = get_interface_gateway("$parentinterface");
951
						$interfaceip = get_interface_ip($parentinterface);
952
						$subnet_bits = get_interface_subnet($parentinterface);
953
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
954
						/* if the remote gateway is in the local subnet, then don't add a route */
955
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
956
							if(is_ipaddr($gatewayip)) {
957
								/* FIXME: does adding route-to and reply-to on the in/outbound
958
								 * rules fix this? smos@ 13-01-2009 */
959
								// log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
960
								mwexec("/sbin/route change -host {$rgip} {$gatewayip}", true);
961
							}
962
						}
963
					}
964
				} 
965
			}
966
		}
967
		fwrite($fd, $spdconf);
968
		fclose($fd);
969

    
970
		/* needed for racoonctl admin socket */
971
		if (!is_dir("/var/db/racoon"))
972
			mkdir("/var/db/racoon/");
973
		
974
		/* mange racoon process */
975
		if (is_process_running("racoon")) {
976
			sleep("0.1");
977
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
978
			/* load SPD without flushing to be safe on config additions or changes. */
979
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
980
		} else {
981
			/* flush SA + SPD entries */
982
			mwexec("/usr/local/sbin/setkey -FP", false);
983
 			sleep("0.1");
984
			mwexec("/usr/local/sbin/setkey -F", false);
985
 			sleep("0.1");
986
 			/* start racoon */
987
			$ipsecdebug = isset($config['ipsec']['racoondebug']) ? "-d -v" : "";
988
			mwexec("/usr/local/sbin/racoon {$ipsecdebug} -f {$g['varetc_path']}/racoon.conf", false);
989
 			sleep("0.1");
990
 			/* load SPD */
991
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
992

    
993
		}
994
		if ($natfilterrules == true)
995
			filter_configure();
996
		/* start filterdns, if necessary */
997
		if (count($filterdns_list) > 0) {
998
			$interval = 60;
999
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
1000
				$interval = $ipseccfg['dns-interval'];
1001

    
1002
			$hostnames = "";
1003
			array_unique($filterdns_list);
1004
			foreach ($filterdns_list as $hostname)
1005
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
1006
			file_put_contents("{$g['varetc_path']}/filterdns-ipsec.hosts", $hostnames);
1007

    
1008
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
1009
			sleep(1);
1010
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/filterdns-ipsec.hosts -d 1");
1011
		}
1012
	
1013
		vpn_ipsec_failover_configure();
1014

    
1015
		if ($g['booting'])
1016
			echo "done\n";
1017
	}
1018

    
1019
	return 0;
1020
}
1021

    
1022
/* Forcefully restart IPsec
1023
 * This is required for when dynamic interfaces reload
1024
 * For all other occasions the normal vpn_ipsec_configure()
1025
 * will gracefully reload the settings without restarting
1026
 */
1027
function vpn_ipsec_force_reload() {
1028
	global $config;
1029
	global $g;
1030

    
1031
	$ipseccfg = $config['ipsec'];
1032

    
1033
	/* kill racoon */
1034
	if(is_process_running("racoon"))
1035
		mwexec("/usr/bin/killall racoon", true);
1036

    
1037
	/* wait for process to die */
1038
	sleep(4);
1039

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

    
1043
	/* wait for flushing to finish */
1044
	sleep(1);
1045

    
1046
	/* if ipsec is enabled, start up again */
1047
	if (isset($ipseccfg['enable'])) {
1048
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1049
		vpn_ipsec_configure();
1050
	}
1051

    
1052
}
1053

    
1054
/* master setup for vpn (mpd) */
1055
function vpn_setup() {
1056
	global $g;
1057

    
1058
	if ($g['platform'] == 'jail')
1059
		return;
1060

    
1061
	/* start pptpd */
1062
	vpn_pptpd_configure();
1063

    
1064
	/* start pppoe server */
1065
	vpn_pppoes_configure();
1066

    
1067
	/* setup l2tp */
1068
	vpn_l2tp_configure();
1069
}
1070

    
1071
function vpn_netgraph_support() {
1072
	$iflist = get_configured_interface_list();
1073
	foreach ($iflist as $iface) {
1074
		$realif = get_real_interface($iface);
1075
		/* Get support for netgraph(4) from the nic */
1076
		$ifinfo = pfSense_get_interface_addresses($realif);
1077
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
1078
                	pfSense_ngctl_attach(".", $realif);
1079
	}
1080
}
1081

    
1082
function vpn_pptpd_configure() {
1083
	global $config, $g;
1084

    
1085
	$syscfg = $config['system'];
1086
	$pptpdcfg = $config['pptpd'];
1087

    
1088
	if ($g['booting']) {
1089
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1090
			return 0;
1091

    
1092
		echo gettext("Configuring PPTP VPN service... ");
1093
	} else {
1094
		/* kill mpd */
1095
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1096

    
1097
		/* wait for process to die */
1098
		sleep(3);
1099

    
1100
		if (is_process_running("mpd -b")) {
1101
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1102
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1103
		}
1104

    
1105
		/* remove mpd.conf, if it exists */
1106
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1107
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1108
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1109
	}
1110

    
1111
	if (empty($pptpdcfg['n_pptp_units'])) {
1112
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1113
		return; 
1114
	}
1115

    
1116
	/* make sure pptp-vpn directory exists */
1117
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1118
		mkdir("{$g['varetc_path']}/pptp-vpn");
1119

    
1120
	switch ($pptpdcfg['mode']) {
1121
		case 'server' :
1122
			/* write mpd.conf */
1123
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1124
			if (!$fd) {
1125
				printf(gettext("Error: cannot open mpd.conf in vpn_pptpd_configure().") . "\n");
1126
				return 1;
1127
			}
1128

    
1129
			$mpdconf = <<<EOD
1130
pptps:
1131

    
1132
EOD;
1133

    
1134
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1135
				$mpdconf .= "	load pt{$i}\n";
1136
			}
1137

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

    
1140
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1141

    
1142
				$mpdconf .= <<<EOD
1143

    
1144
pt{$i}:
1145
	new -i pptpd{$i} pt{$i} pt{$i}
1146
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1147
	load pts
1148

    
1149
EOD;
1150
			}
1151

    
1152
			$mpdconf .=<<<EOD
1153

    
1154
pts:
1155
	set iface disable on-demand
1156
	set iface enable proxy-arp
1157
	set iface enable tcpmssfix
1158
	set iface idle 1800
1159
	set iface up-script /usr/local/sbin/vpn-linkup
1160
	set iface down-script /usr/local/sbin/vpn-linkdown
1161
	set bundle enable multilink
1162
	set bundle enable crypt-reqd
1163
	set link yes acfcomp protocomp
1164
	set link no pap chap
1165
	set link enable chap-msv2
1166
	set link mtu 1460
1167
	set link keep-alive 10 60
1168
	set ipcp yes vjcomp
1169
	set bundle enable compression
1170
	set ccp yes mppc
1171
	set ccp yes mpp-e128
1172
	set ccp yes mpp-stateless
1173

    
1174
EOD;
1175

    
1176
			if (!isset ($pptpdcfg['req128'])) {
1177
				$mpdconf .=<<<EOD
1178
	set ccp yes mpp-e40
1179
	set ccp yes mpp-e56
1180

    
1181
EOD;
1182
			}
1183

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

    
1187
			if (!empty($pptpdcfg['dns1'])) {
1188
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1189
				if (!empty($pptpdcfg['dns2']))
1190
					$mpdconf .= " " . $pptpdcfg['dns2'];
1191
				$mpdconf .= "\n";
1192
			} elseif (isset ($config['dnsmasq']['enable'])) {
1193
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1194
				if ($syscfg['dnsserver'][0])
1195
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1196
				$mpdconf .= "\n";
1197
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1198
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1199
			}
1200

    
1201
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1202
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1203
				$acctport = $authport + 1;
1204
				$mpdconf .=<<<EOD
1205
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1206

    
1207
EOD;
1208
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1209
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1210
				$acctport = $authport + 1;
1211
				$mpdconf .=<<<EOD
1212
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret2']}" {$authport} {$acctport}
1213

    
1214
EOD;
1215
			}
1216
			$mpdconf .=<<<EOD
1217
	set radius retries 3
1218
	set radius timeout 10
1219
	set auth enable radius-auth
1220

    
1221
EOD;
1222

    
1223
				if (isset ($pptpdcfg['radius']['accounting'])) {
1224
					$mpdconf .=<<<EOD
1225
	set auth enable radius-acct
1226
	set radius acct-update 300
1227

    
1228
EOD;
1229
				}
1230
			}
1231

    
1232
			fwrite($fd, $mpdconf);
1233
			fclose($fd);
1234

    
1235
			/* write mpd.links */
1236
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1237
			if (!$fd) {
1238
				printf(gettext("Error: cannot open mpd.links in vpn_pptpd_configure().") . "\n");
1239
				return 1;
1240
			}
1241

    
1242
			$mpdlinks = "";
1243

    
1244
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1245
				$mpdlinks .=<<<EOD
1246

    
1247
pt{$i}:
1248
	set link type pptp
1249
	set pptp enable incoming
1250
	set pptp disable originate
1251
	set pptp disable windowing
1252

    
1253
EOD;
1254
			}
1255

    
1256
			fwrite($fd, $mpdlinks);
1257
			fclose($fd);
1258

    
1259
			/* write mpd.secret */
1260
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1261
			if (!$fd) {
1262
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1263
				return 1;
1264
			}
1265

    
1266
			$mpdsecret = "";
1267

    
1268
			if (is_array($pptpdcfg['user'])) {
1269
				foreach ($pptpdcfg['user'] as $user) {
1270
					$pass = str_replace('\\', '\\\\', $user['password']);
1271
					$pass = str_replace('"', '\"', $pass);
1272
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1273
				}
1274
			}
1275

    
1276
			fwrite($fd, $mpdsecret);
1277
			fclose($fd);
1278
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1279

    
1280
			vpn_netgraph_support();
1281

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

    
1285
			break;
1286

    
1287
		case 'redir' :
1288
			break;
1289
	}
1290

    
1291
	if ($g['booting'])
1292
		echo "done\n";
1293

    
1294
	return 0;
1295
}
1296

    
1297
function vpn_pppoes_configure() {
1298
	global $config;
1299

    
1300
	if (is_array($config['pppoes']['pppoe'])) {
1301
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1302
			vpn_pppoe_configure($pppoe);
1303
	}
1304
}
1305

    
1306
function vpn_pppoe_configure(&$pppoecfg) {
1307
	global $config, $g;
1308

    
1309
	$syscfg = $config['system'];
1310

    
1311
	/* create directory if it does not exist */
1312
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1313
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1314

    
1315
	if ($g['booting']) {
1316
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1317
			return 0;
1318

    
1319
		echo gettext("Configuring PPPoE VPN service... ");
1320
	} else {
1321
		/* kill mpd */
1322
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1323

    
1324
		/* wait for process to die */
1325
		sleep(2);
1326

    
1327
	}
1328

    
1329
	switch ($pppoecfg['mode']) {
1330

    
1331
		case 'server' :
1332

    
1333
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1334

    
1335
			if ($pppoecfg['paporchap'] == "chap")
1336
				$paporchap = "set link enable chap";
1337
			else
1338
				$paporchap = "set link enable pap";
1339

    
1340
			/* write mpd.conf */
1341
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1342
			if (!$fd) {
1343
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1344
				return 1;
1345
			}
1346
			$mpdconf = "\n\n";
1347
			$mpdconf .= "poes:\n";
1348

    
1349
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1350
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1351
			}
1352

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

    
1355
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1356

    
1357
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1358
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1359
				} else {
1360
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1361
				}
1362

    
1363
				$mpdconf .=<<<EOD
1364

    
1365
poes{$pppoecfg['pppoeid']}{$i}:
1366
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1367
	{$isssue_ip_type}
1368
	load pppoe_standard
1369

    
1370
EOD;
1371
			}
1372

    
1373
			$mpdconf .=<<<EOD
1374

    
1375
pppoe_standard:
1376
	set bundle no multilink
1377
	set bundle enable compression
1378
	set auth max-logins 1
1379
	set iface up-script /usr/local/sbin/vpn-linkup
1380
	set iface down-script /usr/local/sbin/vpn-linkdown
1381
	set iface idle 0
1382
	set iface disable on-demand
1383
	set iface disable proxy-arp
1384
	set iface enable tcpmssfix
1385
	set iface mtu 1500
1386
	set link no pap chap
1387
	{$paporchap}
1388
	set link keep-alive 60 180
1389
	set ipcp yes vjcomp
1390
	set ipcp no vjcomp
1391
	set link max-redial -1
1392
	set link mtu 1492
1393
	set link mru 1492
1394
	set ccp yes mpp-e40
1395
	set ccp yes mpp-e128
1396
	set ccp yes mpp-stateless
1397
	set link latency 1
1398
	#set ipcp dns 10.10.1.3
1399
	#set bundle accept encryption
1400

    
1401
EOD;
1402

    
1403
			if (!empty($pppoecfg['dns1'])) {
1404
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1405
				if (!empty($pppoecfg['dns2']))
1406
					$mpdconf .= " " . $pppoecfg['dns2'];
1407
				$mpdconf .= "\n";
1408
			} elseif (isset ($config['dnsmasq']['enable'])) {
1409
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1410
				if ($syscfg['dnsserver'][0])
1411
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1412
				$mpdconf .= "\n";
1413
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1414
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1415
			}
1416

    
1417
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1418
				$radiusport = "";
1419
				$radiusacctport = "";
1420
				if (isset($pppoecfg['radius']['server']['port']))
1421
					$radiusport = $pppoecfg['radius']['server']['port'];
1422
				if (isset($pppoecfg['radius']['server']['acctport']))
1423
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1424
				$mpdconf .=<<<EOD
1425
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1426
	set radius retries 3
1427
	set radius timeout 10
1428
	set auth enable radius-auth
1429

    
1430
EOD;
1431

    
1432
				if (isset ($pppoecfg['radius']['accounting'])) {
1433
					$mpdconf .=<<<EOD
1434
	set auth enable radius-acct
1435

    
1436
EOD;
1437
				}
1438
			}
1439

    
1440
			fwrite($fd, $mpdconf);
1441
			fclose($fd);
1442

    
1443
			/* write mpd.links */
1444
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.links", "w");
1445
			if (!$fd) {
1446
				printf(gettext("Error: cannot open mpd.links in vpn_pppoe_configure().") . "\n");
1447
				return 1;
1448
			}
1449

    
1450
			$mpdlinks = "";
1451

    
1452
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1453
				$mpdlinks .=<<<EOD
1454
			
1455
poes{$pppoecfg['pppoeid']}{$i}:
1456
	set phys type pppoe
1457
        set pppoe iface {$pppoe_interface}
1458
        set pppoe service "*"
1459
        set pppoe disable originate
1460
        set pppoe enable incoming
1461

    
1462
EOD;
1463
			}
1464

    
1465
			fwrite($fd, $mpdlinks);
1466
			fclose($fd);
1467

    
1468
			if ($pppoecfg['username']) {
1469
				/* write mpd.secret */
1470
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1471
				if (!$fd) {
1472
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1473
					return 1;
1474
				}
1475

    
1476
				$mpdsecret = "\n\n";
1477

    
1478
				if (!empty($pppoecfg['username'])) {
1479
					$item = explode(" ", $pppoecfg['username']);
1480
					foreach($item as $userdata) {
1481
						$data = explode(":", $userdata);
1482
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1483
					}
1484
				}
1485

    
1486
				fwrite($fd, $mpdsecret);
1487
				fclose($fd);
1488
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1489
			}
1490

    
1491
			/* Check if previous instance is still up */
1492
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid"))
1493
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1494

    
1495
			/* Get support for netgraph(4) from the nic */
1496
			pfSense_ngctl_attach(".", $pppoe_interface);
1497
			/* fire up mpd */
1498
			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");
1499

    
1500
			break;
1501
	}
1502

    
1503
	if ($g['booting'])
1504
		echo gettext("done") . "\n";
1505

    
1506
	return 0;
1507
}
1508

    
1509
function vpn_l2tp_configure() {
1510
	global $config, $g;
1511

    
1512
	$syscfg = $config['system'];
1513
	$l2tpcfg = $config['l2tp'];
1514

    
1515
	/* create directory if it does not exist */
1516
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1517
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1518

    
1519
	if ($g['booting']) {
1520
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1521
			return 0;
1522

    
1523
		echo gettext("Configuring l2tp VPN service... ");
1524
	} else {
1525
		/* kill mpd */
1526
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1527

    
1528
		/* wait for process to die */
1529
		sleep(8);
1530

    
1531
	}
1532

    
1533
	/* make sure l2tp-vpn directory exists */
1534
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1535
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1536

    
1537
	switch ($l2tpcfg['mode']) {
1538

    
1539
		case 'server' :
1540
			if ($l2tpcfg['paporchap'] == "chap")
1541
				$paporchap = "set link enable chap";
1542
			else
1543
				$paporchap = "set link enable pap";
1544

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

    
1555
EOD;
1556

    
1557
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1558
				$mpdconf .= "	load l2tp{$i}\n";
1559
			}
1560

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

    
1563
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1564

    
1565
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1566
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1567
				} else {
1568
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1569
				}
1570

    
1571
				$mpdconf .=<<<EOD
1572

    
1573
l2tp{$i}:
1574
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1575
	{$isssue_ip_type}
1576
	load l2tp_standard
1577

    
1578
EOD;
1579
			}
1580

    
1581
			$mpdconf .=<<<EOD
1582

    
1583
l2tp_standard:
1584
        set bundle disable multilink
1585
        set bundle enable compression
1586
        set bundle yes crypt-reqd
1587
        set ipcp yes vjcomp
1588
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1589
        set ccp yes mppc
1590
        set iface disable on-demand
1591
        set iface enable proxy-arp
1592
	set iface up-script /usr/local/sbin/vpn-linkup
1593
	set iface down-script /usr/local/sbin/vpn-linkdown
1594
        set link yes acfcomp protocomp
1595
        set link no pap chap
1596
        set link enable chap
1597
        set link keep-alive 10 180
1598

    
1599
EOD;
1600

    
1601
			if (is_ipaddr($l2tpcfg['wins'])) {
1602
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1603
			}
1604
			if (is_ipaddr($l2tpcfg['dns1'])) {
1605
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1606
				if (is_ipaddr($l2tpcfg['dns2']))
1607
					$mpdconf .= " " . $l2tpcfg['dns2'];
1608
				$mpdconf .= "\n";
1609
			} elseif (isset ($config['dnsmasq']['enable'])) {
1610
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1611
				if ($syscfg['dnsserver'][0])
1612
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1613
				$mpdconf .= "\n";
1614
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1615
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1616
			}
1617

    
1618
			if (isset ($l2tpcfg['radius']['enable'])) {
1619
				$mpdconf .=<<<EOD
1620
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1621
	set radius retries 3
1622
	set radius timeout 10
1623
	set auth enable radius-auth
1624

    
1625
EOD;
1626

    
1627
				if (isset ($l2tpcfg['radius']['accounting'])) {
1628
					$mpdconf .=<<<EOD
1629
	set auth enable radius-acct
1630

    
1631
EOD;
1632
				}
1633
			}
1634

    
1635
			fwrite($fd, $mpdconf);
1636
			fclose($fd);
1637

    
1638
			/* write mpd.links */
1639
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1640
			if (!$fd) {
1641
				printf(gettext("Error: cannot open mpd.links in vpn_l2tp_configure().") . "\n");
1642
				return 1;
1643
			}
1644

    
1645
			$mpdlinks = "";
1646

    
1647
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1648
				$mpdlinks .=<<<EOD
1649

    
1650
l2tp{$i}:
1651
	set link type l2tp
1652
        set l2tp enable incoming
1653
        set l2tp disable originate
1654

    
1655
EOD;
1656
			if (!empty($l2tpcfg['secret']))
1657
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1658
			}
1659

    
1660
			fwrite($fd, $mpdlinks);
1661
			fclose($fd);
1662

    
1663
			/* write mpd.secret */
1664
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1665
			if (!$fd) {
1666
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1667
				return 1;
1668
			}
1669

    
1670
			$mpdsecret = "\n\n";
1671

    
1672
			if (is_array($l2tpcfg['user'])) {
1673
				foreach ($l2tpcfg['user'] as $user)
1674
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1675
			}
1676

    
1677
			fwrite($fd, $mpdsecret);
1678
			fclose($fd);
1679
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1680

    
1681
			vpn_netgraph_support();
1682

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

    
1686
			break;
1687

    
1688
		case 'redir' :
1689
			break;
1690
	}
1691

    
1692
	if ($g['booting'])
1693
		echo "done\n";
1694

    
1695
	return 0;
1696
}
1697

    
1698
/* Walk the tunnels for hostname endpoints. If the hostnames 
1699
 * resolve to a different IP now compared to the DNS cache
1700
 * we reload the policies if the endpoint has changed */
1701
function vpn_ipsec_refresh_policies() {
1702
	global $config;
1703
	global $g;
1704

    
1705
	$ipseccfg = $config['ipsec'];
1706
	$a_phase1 = $config['ipsec']['phase1'];
1707
	$a_phase2 = $config['ipsec']['phase2'];
1708

    
1709
	if (isset($ipseccfg['disable'])) {
1710
		return true;
1711
	}
1712

    
1713
	/* Walk the Ipsec tunnel array */
1714
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1715
		return;
1716
	}
1717

    
1718
	foreach ($a_phase1 as $phase1) {
1719
		if (isset($phase1['disabled'])) {
1720
			continue;
1721
		}
1722
		if (is_ipaddr($phase1['remote-gateway'])) {
1723
			continue;
1724
		}
1725
		if (!is_ipaddr($phase1['remote-gateway'])) {
1726
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1727
			$dnscache = trim($dnscache);
1728
			/* we should have the old IP addresses in the dnscache now */
1729
			if($dnscache <> "") {
1730
				$oldphase1 = $phase1;
1731
				$oldphase1['remote-gateway'] = trim($dnscache);
1732
				/* now we need to find all tunnels for this host */
1733
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1734
					continue;
1735
				}
1736
				foreach ($a_phase2 as $phase2) {
1737
					if($phase2['ikeid'] == $phase1['ikeid']) {
1738
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1739
					}
1740
				}
1741
			}
1742
		}
1743
	}
1744

    
1745
	/* process all generated spd.conf files from tmp which are left behind
1746
	 * behind by either changes of dynamic tunnels or manual edits
1747
	 * scandir() is only available in PHP5 */
1748
	$tmpfiles = array();
1749
	$dh  = opendir($g['tmp_path']);
1750
	while (false !== ($filename = readdir($dh))) {
1751
		if(preg_match("/^spd.conf.reload./", $filename)) {
1752
			$tmpfiles[] = $filename;
1753
		}
1754
	}
1755
	sort($tmpfiles);
1756
	foreach($tmpfiles as $tmpfile) {
1757
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1758
		if($ret == 0) {
1759
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1760
		} else {
1761
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1762
		}
1763
	}
1764
}
1765

    
1766
/* reloads the tunnel configuration for a tunnel item
1767
 * Will remove and add SPD polices */
1768
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1769
	global $config;
1770
	global $g;
1771

    
1772
	/* if we are not passed a old tunnel array we create one */
1773
	if(empty($old_phase1)) {
1774
		$old_phase1 = $phase1;
1775
	}
1776
	if(empty($old_phase2)) {
1777
		$old_phase2 = $phase2;
1778
	}
1779

    
1780
	$sad_arr = ipsec_dump_sad();
1781

    
1782
	$ep = ipsec_get_phase1_src($phase1);
1783
	$phase2['localid']['mode'] = $phase2['mode'];
1784
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1785
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1786

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

    
1790
	$old_ep = ipsec_get_phase1_src($old_phase1);
1791
	$old_phase2['localid']['mode'] = $old_phase2['mode'];
1792
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1793
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1794

    
1795
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1796
	 * try to resolve it now and add it to the list for filterdns */
1797
	$rgip = "";
1798
	if (!is_ipaddr($phase1['remote-gateway'])) {
1799
		if(! $g['booting']) {
1800
			$rgip = resolve_retry($phase1['remote-gateway']);
1801
			add_hostname_to_watch($phase1['remote-gateway']);
1802
		} else {
1803
			add_hostname_to_watch($phase1['remote-gateway']);
1804
		}
1805
		if (!is_ipaddr($rgip)) {
1806
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1807
			return false;
1808
		}
1809
	} else {
1810
		$rgip = $phase1['remote-gateway'];
1811
	}
1812
	if (!$ep) {
1813
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1814
		return false;
1815
	}
1816

    
1817
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1818
		log_error(sprintf(gettext("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '%1\$s' new EP '%2\$s'"), $old_ep, $ep));
1819
	}
1820
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1821
		log_error(sprintf(gettext("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '%1\$s' new RG '%2\$s'"), $old_gw, $rgip));
1822
	}
1823

    
1824
	$spdconf = "";
1825
	/* Delete old SPD policies if there are changes between the old and new */
1826
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1827
		if($old_phase2['mode'] == "tunnel6")
1828
			$family = "-6";
1829
		else
1830
			$family = "-4";
1831

    
1832
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1833
			"{$old_remote_subnet} any -P out ipsec " .
1834
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1835
			"{$old_gw}/unique;\n";
1836
		if (!empty($old_phase2['natlocalid']))
1837
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid']);
1838
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1839
			"{$old_local_subnet} any -P in ipsec " .
1840
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1841
			"{$old_ep}/unique;\n";
1842

    
1843
		/* zap any existing SA entries */
1844
		foreach($sad_arr as $sad) {
1845
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1846
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1847
			}
1848
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1849
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1850
			}
1851
		}
1852
	}
1853

    
1854
	if($phase2['mode'] == "tunnel6")
1855
		$family = "-6";
1856
	else
1857
		$family = "-4";
1858

    
1859
	/* Create new SPD entries for the new configuration */
1860
	/* zap any existing SA entries beforehand */
1861
	foreach($sad_arr as $sad) {
1862
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1863
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1864
		}
1865
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1866
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1867
		}
1868
	}
1869
	/* add new SPD policies to replace them */
1870
	if (!isset($phase1['disabled'])) {
1871
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1872
			"{$remote_subnet} any -P out ipsec " .
1873
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1874
			"{$rgip}/unique;\n";
1875

    
1876
		if (!empty($phase2['natlocalid']))
1877
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid']);
1878
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1879
			"{$local_subnet} any -P in ipsec " .
1880
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1881
			"{$ep}/unique;\n";
1882
	}
1883

    
1884
	log_error(sprintf(gettext("Reloading IPsec tunnel '%1\$s'. Previous IP '%2\$s', current IP '%3\$s'. Reloading policy"), $phase1['descr'], $old_gw, $rgip));
1885

    
1886
	$now = time();
1887
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1888
	/* generate temporary spd.conf */
1889
	file_put_contents($spdfile, $spdconf);
1890
	return true;
1891
}
1892

    
1893
function vpn_ipsec_configure_preferoldsa() {
1894
	global $config;
1895
	if(isset($config['ipsec']['preferoldsa']))
1896
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1897
	else
1898
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1899
}
1900

    
1901
?>
(57-57/66)