Project

General

Profile

Download (54.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	/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 (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
937
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
938
				else
939
					$parentinterface = $ph1ent['interface'];
940

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

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

    
987
		}
988
		if ($natfilterrules == true)
989
			filter_configure();
990
		/* start filterdns, if necessary */
991
		if (count($filterdns_list) > 0) {
992
			$interval = 60;
993
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
994
				$interval = $ipseccfg['dns-interval'];
995

    
996
			$hostnames = "";
997
			array_unique($filterdns_list);
998
			foreach ($filterdns_list as $hostname)
999
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
1000
			file_put_contents("{$g['varetc_path']}/filterdns-ipsec.hosts", $hostnames);
1001

    
1002
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
1003
			sleep(1);
1004
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/filterdns-ipsec.hosts -d 1");
1005
		}
1006
	
1007
		vpn_ipsec_failover_configure();
1008

    
1009
		if ($g['booting'])
1010
			echo "done\n";
1011
	}
1012

    
1013
	return 0;
1014
}
1015

    
1016
/* Forcefully restart IPsec
1017
 * This is required for when dynamic interfaces reload
1018
 * For all other occasions the normal vpn_ipsec_configure()
1019
 * will gracefully reload the settings without restarting
1020
 */
1021
function vpn_ipsec_force_reload() {
1022
	global $config;
1023
	global $g;
1024

    
1025
	$ipseccfg = $config['ipsec'];
1026

    
1027
	/* kill racoon */
1028
	if(is_process_running("racoon"))
1029
		mwexec("/usr/bin/killall racoon", true);
1030

    
1031
	/* wait for process to die */
1032
	sleep(4);
1033

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

    
1037
	/* wait for flushing to finish */
1038
	sleep(1);
1039

    
1040
	/* if ipsec is enabled, start up again */
1041
	if (isset($ipseccfg['enable'])) {
1042
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1043
		vpn_ipsec_configure();
1044
	}
1045

    
1046
}
1047

    
1048
/* master setup for vpn (mpd) */
1049
function vpn_setup() {
1050
	global $g;
1051

    
1052
	if ($g['platform'] == 'jail')
1053
		return;
1054

    
1055
	/* start pptpd */
1056
	vpn_pptpd_configure();
1057

    
1058
	/* start pppoe server */
1059
	vpn_pppoes_configure();
1060

    
1061
	/* setup l2tp */
1062
	vpn_l2tp_configure();
1063
}
1064

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

    
1076
function vpn_pptpd_configure() {
1077
	global $config, $g;
1078

    
1079
	$syscfg = $config['system'];
1080
	$pptpdcfg = $config['pptpd'];
1081

    
1082
	if ($g['booting']) {
1083
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1084
			return 0;
1085

    
1086
		echo gettext("Configuring PPTP VPN service... ");
1087
	} else {
1088
		/* kill mpd */
1089
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1090

    
1091
		/* wait for process to die */
1092
		sleep(3);
1093

    
1094
		if (is_process_running("mpd -b")) {
1095
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1096
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1097
		}
1098

    
1099
		/* remove mpd.conf, if it exists */
1100
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1101
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1102
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1103
	}
1104

    
1105
	if (empty($pptpdcfg['n_pptp_units'])) {
1106
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1107
		return; 
1108
	}
1109

    
1110
	/* make sure pptp-vpn directory exists */
1111
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1112
		mkdir("{$g['varetc_path']}/pptp-vpn");
1113

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

    
1123
			$mpdconf = <<<EOD
1124
pptps:
1125

    
1126
EOD;
1127

    
1128
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1129
				$mpdconf .= "	load pt{$i}\n";
1130
			}
1131

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

    
1134
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1135

    
1136
				$mpdconf .= <<<EOD
1137

    
1138
pt{$i}:
1139
	new -i pptpd{$i} pt{$i} pt{$i}
1140
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1141
	load pts
1142

    
1143
EOD;
1144
			}
1145

    
1146
			$mpdconf .=<<<EOD
1147

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

    
1168
EOD;
1169

    
1170
			if (!isset ($pptpdcfg['req128'])) {
1171
				$mpdconf .=<<<EOD
1172
	set ccp yes mpp-e40
1173
	set ccp yes mpp-e56
1174

    
1175
EOD;
1176
			}
1177

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

    
1181
			if (!empty($pptpdcfg['dns1'])) {
1182
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1183
				if (!empty($pptpdcfg['dns2']))
1184
					$mpdconf .= " " . $pptpdcfg['dns2'];
1185
				$mpdconf .= "\n";
1186
			} elseif (isset ($config['dnsmasq']['enable'])) {
1187
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1188
				if ($syscfg['dnsserver'][0])
1189
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1190
				$mpdconf .= "\n";
1191
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1192
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1193
			}
1194

    
1195
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1196
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1197
				$acctport = $authport + 1;
1198
				$mpdconf .=<<<EOD
1199
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1200

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

    
1208
EOD;
1209
			}
1210
			$mpdconf .=<<<EOD
1211
	set radius retries 3
1212
	set radius timeout 10
1213
	set auth enable radius-auth
1214

    
1215
EOD;
1216

    
1217
				if (isset ($pptpdcfg['radius']['accounting'])) {
1218
					$mpdconf .=<<<EOD
1219
	set auth enable radius-acct
1220
	set radius acct-update 300
1221

    
1222
EOD;
1223
				}
1224
			}
1225

    
1226
			fwrite($fd, $mpdconf);
1227
			fclose($fd);
1228

    
1229
			/* write mpd.links */
1230
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1231
			if (!$fd) {
1232
				printf(gettext("Error: cannot open mpd.links in vpn_pptpd_configure().") . "\n");
1233
				return 1;
1234
			}
1235

    
1236
			$mpdlinks = "";
1237

    
1238
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1239
				$mpdlinks .=<<<EOD
1240

    
1241
pt{$i}:
1242
	set link type pptp
1243
	set pptp enable incoming
1244
	set pptp disable originate
1245
	set pptp disable windowing
1246

    
1247
EOD;
1248
			}
1249

    
1250
			fwrite($fd, $mpdlinks);
1251
			fclose($fd);
1252

    
1253
			/* write mpd.secret */
1254
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1255
			if (!$fd) {
1256
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1257
				return 1;
1258
			}
1259

    
1260
			$mpdsecret = "";
1261

    
1262
			if (is_array($pptpdcfg['user'])) {
1263
				foreach ($pptpdcfg['user'] as $user) {
1264
					$pass = str_replace('\\', '\\\\', $user['password']);
1265
					$pass = str_replace('"', '\"', $pass);
1266
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1267
				}
1268
			}
1269

    
1270
			fwrite($fd, $mpdsecret);
1271
			fclose($fd);
1272
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1273

    
1274
			vpn_netgraph_support();
1275

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

    
1279
			break;
1280

    
1281
		case 'redir' :
1282
			break;
1283
	}
1284

    
1285
	if ($g['booting'])
1286
		echo "done\n";
1287

    
1288
	return 0;
1289
}
1290

    
1291
function vpn_pppoes_configure() {
1292
	global $config;
1293

    
1294
	if (is_array($config['pppoes']['pppoe'])) {
1295
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1296
			vpn_pppoe_configure($pppoe);
1297
	}
1298
}
1299

    
1300
function vpn_pppoe_configure(&$pppoecfg) {
1301
	global $config, $g;
1302

    
1303
	$syscfg = $config['system'];
1304

    
1305
	/* create directory if it does not exist */
1306
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1307
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1308

    
1309
	if ($g['booting']) {
1310
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1311
			return 0;
1312

    
1313
		echo gettext("Configuring PPPoE VPN service... ");
1314
	} else {
1315
		/* kill mpd */
1316
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1317

    
1318
		/* wait for process to die */
1319
		sleep(2);
1320

    
1321
	}
1322

    
1323
	switch ($pppoecfg['mode']) {
1324

    
1325
		case 'server' :
1326

    
1327
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1328

    
1329
			if ($pppoecfg['paporchap'] == "chap")
1330
				$paporchap = "set link enable chap";
1331
			else
1332
				$paporchap = "set link enable pap";
1333

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

    
1343
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1344
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1345
			}
1346

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

    
1349
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1350

    
1351
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1352
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1353
				} else {
1354
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1355
				}
1356

    
1357
				$mpdconf .=<<<EOD
1358

    
1359
poes{$pppoecfg['pppoeid']}{$i}:
1360
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1361
	{$isssue_ip_type}
1362
	load pppoe_standard
1363

    
1364
EOD;
1365
			}
1366

    
1367
			$mpdconf .=<<<EOD
1368

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

    
1395
EOD;
1396

    
1397
			if (!empty($pppoecfg['dns1'])) {
1398
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1399
				if (!empty($pppoecfg['dns2']))
1400
					$mpdconf .= " " . $pppoecfg['dns2'];
1401
				$mpdconf .= "\n";
1402
			} elseif (isset ($config['dnsmasq']['enable'])) {
1403
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1404
				if ($syscfg['dnsserver'][0])
1405
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1406
				$mpdconf .= "\n";
1407
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1408
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1409
			}
1410

    
1411
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1412
				$radiusport = "";
1413
				$radiusacctport = "";
1414
				if (isset($pppoecfg['radius']['server']['port']))
1415
					$radiusport = $pppoecfg['radius']['server']['port'];
1416
				if (isset($pppoecfg['radius']['server']['acctport']))
1417
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1418
				$mpdconf .=<<<EOD
1419
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1420
	set radius retries 3
1421
	set radius timeout 10
1422
	set auth enable radius-auth
1423

    
1424
EOD;
1425

    
1426
				if (isset ($pppoecfg['radius']['accounting'])) {
1427
					$mpdconf .=<<<EOD
1428
	set auth enable radius-acct
1429

    
1430
EOD;
1431
				}
1432
			}
1433

    
1434
			fwrite($fd, $mpdconf);
1435
			fclose($fd);
1436

    
1437
			/* write mpd.links */
1438
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.links", "w");
1439
			if (!$fd) {
1440
				printf(gettext("Error: cannot open mpd.links in vpn_pppoe_configure().") . "\n");
1441
				return 1;
1442
			}
1443

    
1444
			$mpdlinks = "";
1445

    
1446
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1447
				$mpdlinks .=<<<EOD
1448
			
1449
poes{$pppoecfg['pppoeid']}{$i}:
1450
	set phys type pppoe
1451
        set pppoe iface {$pppoe_interface}
1452
        set pppoe service "*"
1453
        set pppoe disable originate
1454
        set pppoe enable incoming
1455

    
1456
EOD;
1457
			}
1458

    
1459
			fwrite($fd, $mpdlinks);
1460
			fclose($fd);
1461

    
1462
			if ($pppoecfg['username']) {
1463
				/* write mpd.secret */
1464
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1465
				if (!$fd) {
1466
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1467
					return 1;
1468
				}
1469

    
1470
				$mpdsecret = "\n\n";
1471

    
1472
				if (!empty($pppoecfg['username'])) {
1473
					$item = explode(" ", $pppoecfg['username']);
1474
					foreach($item as $userdata) {
1475
						$data = explode(":", $userdata);
1476
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1477
					}
1478
				}
1479

    
1480
				fwrite($fd, $mpdsecret);
1481
				fclose($fd);
1482
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1483
			}
1484

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

    
1489
			/* Get support for netgraph(4) from the nic */
1490
			pfSense_ngctl_attach(".", $pppoe_interface);
1491
			/* fire up mpd */
1492
			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");
1493

    
1494
			break;
1495
	}
1496

    
1497
	if ($g['booting'])
1498
		echo gettext("done") . "\n";
1499

    
1500
	return 0;
1501
}
1502

    
1503
function vpn_l2tp_configure() {
1504
	global $config, $g;
1505

    
1506
	$syscfg = $config['system'];
1507
	$l2tpcfg = $config['l2tp'];
1508

    
1509
	/* create directory if it does not exist */
1510
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1511
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1512

    
1513
	if ($g['booting']) {
1514
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1515
			return 0;
1516

    
1517
		echo gettext("Configuring l2tp VPN service... ");
1518
	} else {
1519
		/* kill mpd */
1520
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1521

    
1522
		/* wait for process to die */
1523
		sleep(8);
1524

    
1525
	}
1526

    
1527
	/* make sure l2tp-vpn directory exists */
1528
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1529
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1530

    
1531
	switch ($l2tpcfg['mode']) {
1532

    
1533
		case 'server' :
1534
			if ($l2tpcfg['paporchap'] == "chap")
1535
				$paporchap = "set link enable chap";
1536
			else
1537
				$paporchap = "set link enable pap";
1538

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

    
1549
EOD;
1550

    
1551
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1552
				$mpdconf .= "	load l2tp{$i}\n";
1553
			}
1554

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

    
1557
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1558

    
1559
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1560
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1561
				} else {
1562
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1563
				}
1564

    
1565
				$mpdconf .=<<<EOD
1566

    
1567
l2tp{$i}:
1568
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1569
	{$isssue_ip_type}
1570
	load l2tp_standard
1571

    
1572
EOD;
1573
			}
1574

    
1575
			$mpdconf .=<<<EOD
1576

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

    
1593
EOD;
1594

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

    
1612
			if (isset ($l2tpcfg['radius']['enable'])) {
1613
				$mpdconf .=<<<EOD
1614
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1615
	set radius retries 3
1616
	set radius timeout 10
1617
	set auth enable radius-auth
1618

    
1619
EOD;
1620

    
1621
				if (isset ($l2tpcfg['radius']['accounting'])) {
1622
					$mpdconf .=<<<EOD
1623
	set auth enable radius-acct
1624

    
1625
EOD;
1626
				}
1627
			}
1628

    
1629
			fwrite($fd, $mpdconf);
1630
			fclose($fd);
1631

    
1632
			/* write mpd.links */
1633
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1634
			if (!$fd) {
1635
				printf(gettext("Error: cannot open mpd.links in vpn_l2tp_configure().") . "\n");
1636
				return 1;
1637
			}
1638

    
1639
			$mpdlinks = "";
1640

    
1641
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1642
				$mpdlinks .=<<<EOD
1643

    
1644
l2tp{$i}:
1645
	set link type l2tp
1646
        set l2tp enable incoming
1647
        set l2tp disable originate
1648

    
1649
EOD;
1650
			if (!empty($l2tpcfg['secret']))
1651
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1652
			}
1653

    
1654
			fwrite($fd, $mpdlinks);
1655
			fclose($fd);
1656

    
1657
			/* write mpd.secret */
1658
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1659
			if (!$fd) {
1660
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1661
				return 1;
1662
			}
1663

    
1664
			$mpdsecret = "\n\n";
1665

    
1666
			if (is_array($l2tpcfg['user'])) {
1667
				foreach ($l2tpcfg['user'] as $user)
1668
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1669
			}
1670

    
1671
			fwrite($fd, $mpdsecret);
1672
			fclose($fd);
1673
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1674

    
1675
			vpn_netgraph_support();
1676

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

    
1680
			break;
1681

    
1682
		case 'redir' :
1683
			break;
1684
	}
1685

    
1686
	if ($g['booting'])
1687
		echo "done\n";
1688

    
1689
	return 0;
1690
}
1691

    
1692
/* Walk the tunnels for hostname endpoints. If the hostnames 
1693
 * resolve to a different IP now compared to the DNS cache
1694
 * we reload the policies if the endpoint has changed */
1695
function vpn_ipsec_refresh_policies() {
1696
	global $config;
1697
	global $g;
1698

    
1699
	$ipseccfg = $config['ipsec'];
1700
	$a_phase1 = $config['ipsec']['phase1'];
1701
	$a_phase2 = $config['ipsec']['phase2'];
1702

    
1703
	if (isset($ipseccfg['disable'])) {
1704
		return true;
1705
	}
1706

    
1707
	/* Walk the Ipsec tunnel array */
1708
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1709
		return;
1710
	}
1711

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

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

    
1760
/* reloads the tunnel configuration for a tunnel item
1761
 * Will remove and add SPD polices */
1762
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1763
	global $config;
1764
	global $g;
1765

    
1766
	/* if we are not passed a old tunnel array we create one */
1767
	if(empty($old_phase1)) {
1768
		$old_phase1 = $phase1;
1769
	}
1770
	if(empty($old_phase2)) {
1771
		$old_phase2 = $phase2;
1772
	}
1773

    
1774
	$sad_arr = ipsec_dump_sad();
1775

    
1776
	$ep = ipsec_get_phase1_src($phase1);
1777
	$phase2['localid']['mode'] = $phase2['mode'];
1778
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1779
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1780

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

    
1784
	$old_ep = ipsec_get_phase1_src($old_phase1);
1785
	$old_phase2['localid']['mode'] = $old_phase2['mode'];
1786
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1787
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1788

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

    
1811
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1812
		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));
1813
	}
1814
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1815
		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));
1816
	}
1817

    
1818
	$spdconf = "";
1819
	/* Delete old SPD policies if there are changes between the old and new */
1820
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1821
		if($old_phase2['mode'] == "tunnel6")
1822
			$family = "-6";
1823
		else
1824
			$family = "-4";
1825

    
1826
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1827
			"{$old_remote_subnet} any -P out ipsec " .
1828
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1829
			"{$old_gw}/unique;\n";
1830
		if (!empty($old_phase2['natlocalid']))
1831
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid']);
1832
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1833
			"{$old_local_subnet} any -P in ipsec " .
1834
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1835
			"{$old_ep}/unique;\n";
1836

    
1837
		/* zap any existing SA entries */
1838
		foreach($sad_arr as $sad) {
1839
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1840
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1841
			}
1842
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1843
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1844
			}
1845
		}
1846
	}
1847

    
1848
	if($phase2['mode'] == "tunnel6")
1849
		$family = "-6";
1850
	else
1851
		$family = "-4";
1852

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

    
1870
		if (!empty($phase2['natlocalid']))
1871
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid']);
1872
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1873
			"{$local_subnet} any -P in ipsec " .
1874
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1875
			"{$ep}/unique;\n";
1876
	}
1877

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

    
1880
	$now = time();
1881
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1882
	/* generate temporary spd.conf */
1883
	file_put_contents($spdfile, $spdconf);
1884
	return true;
1885
}
1886

    
1887
function vpn_ipsec_configure_preferoldsa() {
1888
	global $config;
1889
	if(isset($config['ipsec']['preferoldsa']))
1890
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1891
	else
1892
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1893
}
1894

    
1895
?>
(57-57/66)