Project

General

Profile

Download (56 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

    
88
	/* get the automatic ping_hosts.sh ready */
89
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
90
	touch("{$g['vardb_path']}/ipsecpinghosts");
91

    
92
	vpn_ipsec_configure_preferoldsa();
93

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

    
100
	if (!isset($ipseccfg['enable'])) {
101
		/* try to stop racoon*/
102
		killbypid("{$g['varrun_path']}/racoon.pid");
103
		/* Stop dynamic monitoring */
104
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
105

    
106
		/* kill racoon forcefully */
107
		if (is_process_running("racoon"))
108
			mwexec("/usr/bin/killall -9 racoon", true);
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
		mwexec("/sbin/ifconfig enc0 down");
119
		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
120

    
121
		return true;
122
	} else {
123
		mwexec("/sbin/ifconfig enc0 up");
124
		mwexec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
125
		/* needed for racoonctl admin socket */
126
		if (!is_dir("/var/db/racoon"))
127
			mkdir("/var/db/racoon/");
128
		/* needed for config files */
129
		if (!is_dir("{$g['varetc_path']}/ipsec"))
130
			mkdir("{$g['varetc_path']}/ipsec");
131
		
132

    
133
		if ($g['booting'])
134
			echo gettext("Configuring IPsec VPN... ");
135

    
136
		/* fastforwarding is not compatible with ipsec tunnels */
137
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
138

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

    
146
			$ipsecpinghosts = "";
147
			/* step through each phase1 entry */
148
			$ipsecpinghosts = "";
149
			foreach ($a_phase1 as $ph1ent) {
150
				if (isset($ph1ent['disabled']))
151
					continue;
152

    
153
				$ep = ipsec_get_phase1_src($ph1ent);
154
				if (!is_ipaddr($ep))
155
					continue;
156

    
157
				if(!in_array($ep,$ipmap))
158
					$ipmap[] = $ep;
159

    
160
				/* see if this tunnel has a hostname for the remote-gateway. If so,
161
				   try to resolve it now and add it to the list for filterdns */
162

    
163
				if (isset ($ph1ent['mobile']))
164
					continue;
165

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

    
168
				if (!is_ipaddr($rg)) {
169
					$filterdns_list[] = "{$rg}";
170
					add_hostname_to_watch($rg);
171
					if(! $g['booting'])
172
						$rg = resolve_retry($rg);
173
					if (!is_ipaddr($rg))
174
						continue;
175
				}
176
				if(array_search($rg, $rgmap)) {
177
					log_error("The remote gateway {$rg} already exists on another phase 1 entry");
178
					continue;
179
				}
180
				$rgmap[$ph1ent['remote-gateway']] = $rg;
181

    
182
				if (is_array($a_phase2)) {
183
					/* step through each phase2 entry */
184
					foreach ($a_phase2 as $ph2ent) {
185
						$ikeid = $ph2ent['ikeid'];
186

    
187
						if (isset($ph2ent['disabled']))
188
							continue;
189

    
190
						if ($ikeid != $ph1ent['ikeid'])
191
							continue;
192

    
193
						$ph2ent['localid']['mode'] = $ph2ent['mode'];
194
						/* add an ipsec pinghosts entry */
195
						if ($ph2ent['pinghost']) {
196
							if (!is_array($iflist))
197
								$iflist = get_configured_interface_list();
198
							foreach ($iflist as $ifent => $ifname) {
199
								if(is_ipaddrv6($ph2ent['pinghost'])) {
200
									$interface_ip = get_interface_ipv6($ifent);
201
									if(!is_ipaddrv6($interface_ip))
202
										continue;
203
									$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
204
									if (ip_in_subnet($interface_ip, $local_subnet)) {
205
										$srcip = $interface_ip;
206
										break;
207
									}
208
								} else {
209
									$interface_ip = get_interface_ip($ifent);
210
									if(!is_ipaddrv4($interface_ip))
211
										continue;
212
									$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
213
									if ($local_subnet == "0.0.0.0/0" || ip_in_subnet($interface_ip, $local_subnet)) {
214
										$srcip = $interface_ip;
215
										break;
216
									}
217
								}
218
							}
219
							$dstip = $ph2ent['pinghost'];
220
							if(is_ipaddrv6($dstip)) {
221
								$family = "inet6";
222
							} else {
223
								$family = "inet";
224
							}
225
							if (is_ipaddr($srcip))
226
								$ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n";
227
						}
228
					}
229
					@file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts);
230
					unset($ipsecpinghosts);
231
				}
232
			}
233
		}
234

    
235
		/* generate CA certificates files */
236
		if (is_array($config['ca']) && count($config['ca'])) {
237
			foreach ($config['ca'] as $ca) {
238
				if (!isset($ca['crt'])) {
239
					log_error(sprintf(gettext("Error: Invalid certificate info for %s"), $ca['descr']));
240
					continue;
241
				}
242
				$cert = base64_decode($ca['crt']);
243
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
244
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
245
					log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $ca['descr']));
246
					continue;
247
				}
248
				$fname = "{$g['varetc_path']}/ipsec/{$x509cert['hash']}.0";
249
				if (!@file_put_contents($fname, $cert)) {
250
					log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $ca['descr']));
251
					continue;
252
				}
253
				unset($cert);
254
			}
255
		}
256
		
257
		$pskconf = "";
258

    
259
		if (is_array($a_phase1) && count($a_phase1)) {
260
			foreach ($a_phase1 as $ph1ent) {
261

    
262
				if (isset($ph1ent['disabled']))
263
					continue;
264

    
265
				if (strstr($ph1ent['authentication_method'],'rsa'))
266
					continue;
267

    
268
				$peerid_type = $ph1ent['peerid_type'];
269

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

    
276
					case "address";
277
						$peerid_data = $ph1ent['peerid_data'];
278
						break;
279

    
280
					case "fqdn";
281
					case "keyid tag";
282
					case "user_fqdn";
283
						$peerid_data = $ph1ent['peerid_data'];
284
						break;
285
				}
286

    
287
				if (!empty($peerid_data) && !empty($ph1ent['pre-shared-key']))
288
					$pskconf .= trim($peerid_data) . "\t" . trim($ph1ent['pre-shared-key']) . "\n";
289
			}
290
		}
291

    
292
		/* Add user PSKs */
293
		foreach ($config['system']['user'] as $user) {
294
			if (!empty($user['ipsecpsk'])) {
295
				$pskconf .= "{$user['name']}\t{$user['ipsecpsk']}\n";
296
			}
297
		}
298

    
299
		/* add PSKs for mobile clients */
300
		if (is_array($ipseccfg['mobilekey'])) {
301
			foreach ($ipseccfg['mobilekey'] as $key) {
302
				$pskconf .= "{$key['ident']}\t{$key['pre-shared-key']}\n";
303
			}
304
		}
305

    
306
		@file_put_contents("{$g['varetc_path']}/ipsec/psk.txt", $pskconf);
307
		chmod("{$g['varetc_path']}/ipsec/psk.txt", 0600);
308
		unset($pskconf);
309
			
310
		/* begin racoon.conf */
311
		$racoonconf = "";
312
		if ((is_array($a_phase1) && count($a_phase1)) || (is_array($a_phase2) && count($a_phase2))) {
313

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

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

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

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

    
336
				if (!empty($a_client['user_source']))
337
					$racoonconf .= "\tauth_source external;\n";
338
				if (!empty($a_client['group_source']) && $a_client['group_source'] != "none")
339
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
340

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

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

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

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

    
355
					$net_list = '';
356

    
357
					foreach ($a_phase2 as $ph2ent) {
358

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

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

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

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

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

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

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

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

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

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

    
405
				if ($a_client['login_banner']) {
406
					@file_put_contents("{$g['varetc_path']}/ipsec/racoon.motd", $a_client['login_banner']);
407
					$racoonconf .= "\tbanner \"{$g['varetc_path']}/ipsec/racoon.motd\";\n";
408
				}
409

    
410
				if (isset($a_client['save_passwd']))
411
					$racoonconf .= "\tsave_passwd on;\n";
412

    
413
				$racoonconf .= "}\n\n";
414
			}
415
			/* end mode_cfg section */
416
			
417
			if ($a_client['user_source'] != "none") {
418
				$authcfgs = explode(",", $a_client['user_source']);
419
				$sed = "\$authmodes=array(";
420
				$firstsed = 0;
421
				foreach ($authcfgs as $authcfg) {
422
					if ($authcfg == "system")
423
						$authcfg = "Local Database";
424
					if ($firstsed > 0)
425
						$sed .= ",";
426
					$firstsed = 1;
427
					$sed .= "\"{$authcfg}\"";
428
				}
429
				$sed .= ");\\\n";
430
				if ($a_client['strictusercn'])
431
					$sed .= "\$strictusercn = true;";
432
				mwexec("/bin/cat /etc/inc/ipsec.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/ipsec/ipsec.php");
433
				mwexec("/bin/chmod a+x {$g['varetc_path']}/ipsec/ipsec.php");
434
				$racoonconf .= "extcfg { script \"{$g['varetc_path']}/ipsec/ipsec.php\" }\n";
435
			}
436

    
437
			/* begin remote sections */
438
			if (is_array($a_phase1) && count($a_phase1)) {
439
				/* begin remote */
440
				foreach ($a_phase1 as $ph1ent) {
441

    
442
					if (isset($ph1ent['disabled']))
443
						continue;
444

    
445
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
446
						continue;
447

    
448
					$ikeid = $ph1ent['ikeid'];
449

    
450
					$ep = ipsec_get_phase1_src($ph1ent);
451
					if (!$ep)
452
						continue;
453

    
454
					if (!isset($ph1ent['mobile'])) {
455
						$rgip = $rgmap[$ph1ent['remote-gateway']];
456
						if (!$rgip)
457
							continue;
458
					}
459

    
460
					$myid_type = $ph1ent['myid_type'];
461

    
462
					switch ($myid_type) {
463

    
464
						case "myaddress":
465
							$myid_type = "address";
466
							$myid_data = $ep;
467
							break;
468

    
469
						case "dyn_dns":
470
							$myid_type = "address";
471
							$myid_data = resolve_retry($ph1ent['myid_data']);
472
							break;
473

    
474
						case "address";
475
							$myid_data = $ph1ent['myid_data'];
476
							break;
477

    
478
						case "fqdn";
479
						case "keyid tag";
480
						case "user_fqdn";
481
						case "asn1dn";
482
							$myid_data = $ph1ent['myid_data'];
483
							if( $myid_data )
484
								$myid_data = "\"".$myid_data."\"";
485
							break;
486
					}
487

    
488
					$peerid_type = $ph1ent['peerid_type'];
489

    
490
					switch ($peerid_type) {
491
						case "peeraddress":
492
							$peerid_type = "address";
493
							$peerid_data = $rgip;
494
							break;
495

    
496
						case "address";
497
							$peerid_data = $ph1ent['peerid_data'];
498
							break;
499

    
500
						case "fqdn";
501
						case "keyid tag";
502
						case "user_fqdn";
503
						case "asn1dn";
504
							$peerid_data = $ph1ent['peerid_data'];
505
							if( $peerid_data )
506
								$peerid_data = "\"".$peerid_data."\"";
507
							break;
508
					}
509

    
510
					$natt = "off";
511
					if (isset($ph1ent['nat_traversal']))
512
						$natt = $ph1ent['nat_traversal'];
513

    
514
					$init = "on";
515
					$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "off";
516
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
517
					$passive = "";
518
					if (isset($ph1ent['mobile'])) {
519
						$rgip = "anonymous";
520
						$passive = "passive on;";
521
						$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
522
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
523
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
524
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "on";
525
						} else {
526
							$init = "off";
527
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "unique";
528
						}
529
					}
530

    
531
					$dpdline1 = '';
532
					$dpdline2 = '';
533
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
534
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
535
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
536
					}
537

    
538
					if (isset ($ph1ent['authentication_method']))
539
						$authmethod = $ph1ent['authentication_method'];
540
					else
541
						$authmethod = 'pre_shared_key';
542

    
543
					$certline = '';
544

    
545
					if (strstr($authmethod,'rsa')) {
546

    
547
						$cert = lookup_cert($ph1ent['certref']);
548

    
549
						if (!$cert)
550
						{
551
							log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
552
							continue;
553
						}
554

    
555
						$certfile = "cert-{$ikeid}.crt";
556
						$certpath = "{$g['varetc_path']}/ipsec/{$certfile}";
557

    
558
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
559
						{
560
							log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
561
							continue;
562
						}
563

    
564
						chmod($certpath, 0600);
565

    
566
						$keyfile = "cert-{$ikeid}.key";
567
						$keypath = "{$g['varetc_path']}/ipsec/{$keyfile}";
568

    
569
						if (!file_put_contents($keypath, base64_decode($cert['prv'])))
570
						{
571
							log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
572
							continue;
573
						}
574

    
575
						chmod($keypath, 0600);
576

    
577
						$ca = lookup_ca($ph1ent['caref']);
578
						if ($ca) {
579
							$cafile = "ca-{$ikeid}.crt";
580
							$capath = "{$g['varetc_path']}/ipsec/{$cafile}";
581

    
582
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
583
							{
584
								log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
585
								continue;
586
							}
587

    
588
							chmod($capath, 0600);
589
							$caline = "ca_type x509 \"{$cafile}\";";
590
						}
591

    
592
						$certline = "certificate_type x509 \"{$certfile}\" \"{$keyfile}\";";
593

    
594
					}
595

    
596
					$ealgos = '';
597
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
598
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
599
					if ($ealg_kl)
600
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
601
					else
602
						$ealgos = $ealgos.$ealg_id;
603

    
604
					$lifeline = '';
605
					if ($ph1ent['lifetime'])
606
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
607

    
608
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
609
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
610
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
611
					}
612

    
613
					/* add remote section to configuration */
614

    
615
					$racoonconf .=<<<EOD
616

    
617
remote {$rgip}
618
{
619
	ph1id {$ikeid};
620
	exchange_mode {$ph1ent['mode']};
621
	my_identifier {$myid_type} {$myid_data};
622
	{$peerid_spec}
623
	ike_frag on;
624
	generate_policy = {$genp};
625
	initial_contact = {$init};
626
	nat_traversal = {$natt};
627
	{$certline}
628
	{$caline}
629
	{$dpdline1}
630
	{$dpdline2}
631
	support_proxy on;
632
	proposal_check {$pcheck};
633
	{$passive}
634

    
635
	proposal
636
	{
637
		authentication_method {$authmethod};
638
		encryption_algorithm ${ealgos};
639
		hash_algorithm {$ph1ent['hash-algorithm']};
640
		dh_group {$ph1ent['dhgroup']};
641
		${lifeline}
642
	}
643
}
644

    
645
EOD;
646
				}
647
				/* end remote */
648
			}
649
			/* end remote sections */
650
		
651
			/* begin sainfo sections */
652
			if (is_array($a_phase2) && count($a_phase2)) {
653

    
654
				/* begin sainfo */
655
				foreach ($a_phase2 as $ph2ent) {
656

    
657
					$ikeid = $ph2ent['ikeid'];
658

    
659
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
660
						continue;
661

    
662
					if (isset($ph1ent['disabled']))
663
						continue;
664

    
665
					if (isset($ph2ent['disabled']))
666
						continue;
667

    
668
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
669
						continue;
670

    
671
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
672

    
673
						$localid_type = $ph2ent['localid']['type'];
674
						$ph2ent['localid']['mode'] = $ph2ent['mode'];
675
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
676
						/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
677
						if (($localid_type == "none") ||
678
							(($ph1ent['authentication_method'] == "xauth_psk_server") ||
679
							($ph1ent['authentication_method'] == "pre_shared_key"))
680
							&& isset($ph1ent['mobile'])
681
							&& (ipsec_get_number_of_phase2($ikeid)==1))
682
							$localid_spec = " ";
683
						else {
684
							if ($localid_type != "address") {
685
								$localid_type = "subnet";
686
							}
687
							// Don't let an empty subnet into racoon.conf, it can cause parse errors. Ticket #2201.
688
							if (!is_ipaddr($localid_data) && !is_subnet($localid_data) && ($localid_data != "0.0.0.0/0")) {
689
								log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet.");
690
								continue;
691
							}
692
							$localid_spec = "{$localid_type} {$localid_data} any";
693
							if (!empty($ph2ent['natlocalid'])) {
694
								$natlocalid_data =  ipsec_idinfo_to_cidr($ph2ent['natlocalid']);
695
								if ($ph2ent['natlocalid']['type'] != "address") {
696
									if (is_subnet($natlocalid_data))
697
										$localid_spec .= " nat subnet {$natlocalid_data} any";
698
								} else {
699
									if (is_ipaddr($natlocalid_data))
700
										$localid_spec .= " nat address {$natlocalid_data} any";
701
								}
702
							}
703
						}
704

    
705
						if (!isset($ph2ent['mobile'])) {
706
							$remoteid_type = $ph2ent['remoteid']['type'];
707
							if ($remoteid_type != "address")
708
								$remoteid_type = "subnet";
709

    
710
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
711
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
712
						} else
713
							$remoteid_spec = "anonymous";
714

    
715
					} else {
716
						$rgip = $rgmap[$ph1ent['remote-gateway']];
717

    
718
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
719
							($ph1ent['authentication_method'] == "pre_shared_key"))
720
							&& isset($ph1ent['mobile']))
721
							$localid_spec = " ";
722
						else {
723
							$localid_data = ipsec_get_phase1_src($ph1ent);
724
							if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
725
							$localid_spec = "address {$localid_data}";
726
						}
727
						if (!isset($ph2ent['mobile'])) {
728
							$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
729
							if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
730
							$remoteid_spec = "address {$remoteid_data}";
731
						} else
732
							$remoteid_spec = "anonymous";
733
					}
734

    
735
					if($ph2ent['protocol'] == 'esp') {
736

    
737
						$ealgos = '';
738

    
739
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
740

    
741
							$ealg_id = $ealg['name'];
742
							$ealg_kl = $ealg['keylen'];
743

    
744
							if ($ealg_kl) {
745
								if( $ealg_kl == "auto" ) {
746
									/*   This seems to be required on my system and was not reproducable
747
									 *   on other systems.   For some reason $p2_ealgos is not defined
748
									 *   and needs to be read back in!?  -sullrich Aug 26, 2009 
749
									 */
750
									if(!$p2_ealgos)
751
										require("ipsec.inc");
752
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
753
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
754
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
755
									/* in some cases where include ordering is suspect these variables
756
									   are somehow 0 and we enter this loop forever and timeout after 900
757
									   seconds wrecking bootup */
758
									if($key_hi != 0 and $key_lo !=0 and $key_step !=0) {
759
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
760
//											Uncomment the next line if you want to test the comment 5 lines up.											
761
//											echo "$keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step \n";
762
											if ($ealgos)
763
												$ealgos = $ealgos.", ";
764
											$ealgos = $ealgos.$ealg_id." ".$keylen;
765
										}
766
									}
767
								} else {
768
									if ($ealgos)
769
										$ealgos = $ealgos.", ";
770
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
771
								}
772
							} else {
773
								if ($ealgos)
774
									$ealgos = $ealgos.", ";
775
								$ealgos = $ealgos.$ealg_id;
776
							}
777
						}
778

    
779
						$ealgosline = "encryption_algorithm {$ealgos};";
780

    
781
					} else {
782

    
783
						$ealgosline = "encryption_algorithm null_enc;";
784
					}
785

    
786
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
787
					$halgosline = "authentication_algorithm {$halgos};";
788

    
789
					$pfsline = '';
790
					if ($ph2ent['pfsgroup'])
791
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
792
					if (isset($a_client['pfs_group'])) {
793
						$pfsline = '';
794
						if ($a_client['pfs_group'])
795
							$pfsline = "pfs_group {$a_client['pfs_group']};";
796
					}
797

    
798
					$lifeline = '';
799
					if ($ph2ent['lifetime'])
800
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
801

    
802
					/* add sainfo section to configuration */
803
					
804
					$racoonconf .=<<<EOD
805
					
806
sainfo {$localid_spec} {$remoteid_spec}
807
{
808
	remoteid {$ikeid};
809
	{$ealgosline}
810
	{$halgosline}
811
	{$pfsline}
812
	{$lifeline}
813
	compression_algorithm deflate;
814
}
815

    
816
EOD;
817
				}
818
				/* end sainfo */
819
			}
820
			/* end sainfo sections */
821
		}
822
		@file_put_contents("{$g['varetc_path']}/ipsec/racoon.conf", $racoonconf);
823
		unset($racoonconf);
824
		/* end racoon.conf */
825

    
826
		/* generate IPsec policies */
827
		/* generate spd.conf */
828
		$spdconf = "";
829
		$natfilterrules = false;
830
		if (is_array($a_phase2) && count($a_phase2)) {
831
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
832
			if ($config['interfaces']['lan']) {
833
				$lanip = get_interface_ip("lan");
834
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
835
					$lansn = get_interface_subnet("lan");
836
					$lansa = gen_subnet($lanip, $lansn);
837
					$spdconf .= "spdadd -4 {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
838
					$spdconf .= "spdadd -4 {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
839
				}
840
				$lanipv6 = get_interface_ipv6("lan");
841
				if (!empty($lanipv6) && is_ipaddrv6($lanipv6)) {
842
					$lansnv6 = get_interface_subnetv6("lan");
843
					$lansav6 = gen_subnetv6($lanipv6, $lansnv6);
844
					$spdconf .= "spdadd -6 {$lanipv6}/128 {$lansav6}/{$lansnv6} any -P out none;\n";
845
					$spdconf .= "spdadd -6 {$lansav6}/{$lansnv6} {$lanipv6}/128 any -P in none;\n";
846
				}
847
			}
848

    
849
			foreach ($a_phase2 as $ph2ent) {
850

    
851
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
852
					continue;
853

    
854
				if (isset($ph1ent['mobile']))
855
					continue;
856

    
857
				if (isset($ph1ent['disabled']))
858
					continue;
859

    
860
				if (isset($ph2ent['disabled']))
861
					continue;
862

    
863
				$ep = ipsec_get_phase1_src($ph1ent);
864
				if (!$ep)
865
					continue;
866

    
867
				$rgip = $rgmap[$ph1ent['remote-gateway']];
868
				if(!is_ipaddr($rgip))
869
					continue;
870

    
871
				$ph2ent['localid']['mode'] = $ph2ent['mode'];
872
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
873
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
874

    
875
				if(($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == 'tunnel6')) {
876
					// Error will be logged above, no need to log this twice. #2201
877
					if (!is_subnet($localid))
878
						continue;
879

    
880
					if($ph2ent['mode'] == "tunnel6")
881
						$family = "-6";
882
					else
883
						$family = "-4";
884

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

    
888
					if (!empty($ph2ent['natlocalid'])) {
889
						$natlocalid = ipsec_idinfo_to_cidr($ph2ent['natlocalid'],true);
890
						$spdconf .= "spdadd {$family} {$remoteid} {$natlocalid} any -P in ipsec " .
891
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
892
						$natfilterrules = true;
893
					} else
894
						$spdconf .= "spdadd {$family} {$remoteid} {$localid} any -P in ipsec " .
895
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
896

    
897
				} else {
898

    
899
					$localid_data = ipsec_get_phase1_src($ph1ent);
900
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
901

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

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

    
908
				}
909

    
910
				/* static route needed? */
911
				if (is_ipaddr($ph1ent['interface'])) {
912
					$vip = find_virtual_ip_alias($ph1ent['interface']);
913
					if (preg_match("/^carp|^[a-z0-9]+_vip/i", $vip['interface']))
914
						$parentinterface = link_carp_interface_to_parent($vip['interface']);
915
					else
916
						$parentinterface = $vip['interface'];
917
				} else if (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
918
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
919
				else
920
					$parentinterface = $ph1ent['interface'];
921

    
922
				if (is_ipaddr($rgip)) {
923
					/* add endpoint routes to correct gateway on interface */
924
					if (interface_has_gateway($parentinterface)) {
925
						$gatewayip = get_interface_gateway("$parentinterface");
926
						$interfaceip = get_interface_ip($parentinterface);
927
						$subnet_bits = get_interface_subnet($parentinterface);
928
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
929
						/* if the remote gateway is in the local subnet, then don't add a route */
930
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
931
							if(is_ipaddr($gatewayip)) {
932
								/* FIXME: does adding route-to and reply-to on the in/outbound
933
								 * rules fix this? smos@ 13-01-2009 */
934
								// log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
935
								mwexec("/sbin/route change -host {$rgip} {$gatewayip}", true);
936
							}
937
						}
938
					}
939
				} 
940
			}
941
		}
942
		@file_put_contents("{$g['varetc_path']}/ipsec/spd.conf", $spdconf);
943
		unset($spdconf);
944

    
945
		/* mange racoon process */
946
		if (is_process_running("racoon")) {
947
			sleep("0.1");
948
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
949
			/* load SPD without flushing to be safe on config additions or changes. */
950
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/ipsec/spd.conf", false);
951
		} else {
952
			/* flush SA + SPD entries */
953
			mwexec("/usr/local/sbin/setkey -FP", false);
954
 			sleep("0.1");
955
			mwexec("/usr/local/sbin/setkey -F", false);
956
 			sleep("0.1");
957
 			/* start racoon */
958
			$ipsecdebug = isset($config['ipsec']['racoondebug']) ? "-d -v" : "";
959
			mwexec("/usr/local/sbin/racoon {$ipsecdebug} -f {$g['varetc_path']}/ipsec/racoon.conf", false);
960
 			sleep("0.1");
961
 			/* load SPD */
962
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/ipsec/spd.conf", false);
963

    
964
		}
965
		if ($natfilterrules == true)
966
			filter_configure();
967
		/* start filterdns, if necessary */
968
		if (count($filterdns_list) > 0) {
969
			$interval = 60;
970
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
971
				$interval = $ipseccfg['dns-interval'];
972

    
973
			$hostnames = "";
974
			array_unique($filterdns_list);
975
			foreach ($filterdns_list as $hostname)
976
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
977
			file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
978
			unset($hostnames);
979

    
980
			if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid"))
981
				sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
982
			else {
983
				mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
984
			}
985
		} else {
986
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
987
			@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
988
		}
989
	
990
		vpn_ipsec_failover_configure();
991

    
992
		if ($g['booting'])
993
			echo "done\n";
994
	}
995

    
996
	return 0;
997
}
998

    
999
/* 
1000
 * Forcefully restart IPsec
1001
 * This is required for when dynamic interfaces reload
1002
 * For all other occasions the normal vpn_ipsec_configure()
1003
 * will gracefully reload the settings without restarting
1004
 */
1005
function vpn_ipsec_force_reload() {
1006
	global $config;
1007
	global $g;
1008

    
1009
	$ipseccfg = $config['ipsec'];
1010

    
1011
	/* send a SIGKILL to be sure */
1012
	killbypid("{$g['varrun_path']}/racoon.pid");
1013

    
1014
	/* wait for process to die */
1015
	sleep(4);
1016

    
1017
	/* kill racoon forcefully */
1018
	if (is_process_running("racoon"))
1019
		mwexec("/usr/bin/killall -9 racoon", true);
1020

    
1021
	/* wait for flushing to finish */
1022
	sleep(1);
1023

    
1024
	/* if ipsec is enabled, start up again */
1025
	if (isset($ipseccfg['enable'])) {
1026
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1027
		vpn_ipsec_configure();
1028
	}
1029
}
1030

    
1031
/* master setup for vpn (mpd) */
1032
function vpn_setup() {
1033
	global $g;
1034

    
1035
	if ($g['platform'] == 'jail')
1036
		return;
1037

    
1038
	/* start pptpd */
1039
	vpn_pptpd_configure();
1040

    
1041
	/* start pppoe server */
1042
	vpn_pppoes_configure();
1043

    
1044
	/* setup l2tp */
1045
	vpn_l2tp_configure();
1046
}
1047

    
1048
function vpn_netgraph_support() {
1049
	$iflist = get_configured_interface_list();
1050
	foreach ($iflist as $iface) {
1051
		$realif = get_real_interface($iface);
1052
		/* Get support for netgraph(4) from the nic */
1053
		$ifinfo = pfSense_get_interface_addresses($realif);
1054
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
1055
                	pfSense_ngctl_attach(".", $realif);
1056
	}
1057
}
1058

    
1059
function vpn_pptpd_configure() {
1060
	global $config, $g;
1061

    
1062
	$syscfg = $config['system'];
1063
	$pptpdcfg = $config['pptpd'];
1064

    
1065
	if ($g['booting']) {
1066
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1067
			return 0;
1068

    
1069
		echo gettext("Configuring PPTP VPN service... ");
1070
	} else {
1071
		/* kill mpd */
1072
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1073

    
1074
		/* wait for process to die */
1075
		sleep(3);
1076

    
1077
		if (is_process_running("mpd -b")) {
1078
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1079
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1080
		}
1081

    
1082
		/* remove mpd.conf, if it exists */
1083
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1084
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1085
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1086
	}
1087

    
1088
	if (empty($pptpdcfg['n_pptp_units'])) {
1089
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1090
		return; 
1091
	}
1092

    
1093
	/* make sure pptp-vpn directory exists */
1094
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1095
		mkdir("{$g['varetc_path']}/pptp-vpn");
1096

    
1097
	switch ($pptpdcfg['mode']) {
1098
		case 'server' :
1099
			/* write mpd.conf */
1100
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1101
			if (!$fd) {
1102
				printf(gettext("Error: cannot open mpd.conf in vpn_pptpd_configure().") . "\n");
1103
				return 1;
1104
			}
1105

    
1106
			$mpdconf = <<<EOD
1107
pptps:
1108

    
1109
EOD;
1110

    
1111
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1112
				$mpdconf .= "	load pt{$i}\n";
1113
			}
1114

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

    
1117
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1118

    
1119
				$mpdconf .= <<<EOD
1120

    
1121
pt{$i}:
1122
	new -i pptpd{$i} pt{$i} pt{$i}
1123
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1124
	load pts
1125

    
1126
EOD;
1127
			}
1128

    
1129
			$mpdconf .=<<<EOD
1130

    
1131
pts:
1132
	set iface disable on-demand
1133
	set iface enable proxy-arp
1134
	set iface enable tcpmssfix
1135
	set iface idle 1800
1136
	set iface up-script /usr/local/sbin/vpn-linkup
1137
	set iface down-script /usr/local/sbin/vpn-linkdown
1138
	set bundle enable multilink
1139
	set bundle enable crypt-reqd
1140
	set link yes acfcomp protocomp
1141
	set link no pap chap
1142
	set link enable chap-msv2
1143
	set link mtu 1460
1144
	set link keep-alive 10 60
1145
	set ipcp yes vjcomp
1146
	set bundle enable compression
1147
	set ccp yes mppc
1148
	set ccp yes mpp-e128
1149
	set ccp yes mpp-stateless
1150

    
1151
EOD;
1152

    
1153
			if (!isset ($pptpdcfg['req128'])) {
1154
				$mpdconf .=<<<EOD
1155
	set ccp yes mpp-e40
1156
	set ccp yes mpp-e56
1157

    
1158
EOD;
1159
			}
1160

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

    
1164
			if (!empty($pptpdcfg['dns1'])) {
1165
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1166
				if (!empty($pptpdcfg['dns2']))
1167
					$mpdconf .= " " . $pptpdcfg['dns2'];
1168
				$mpdconf .= "\n";
1169
			} elseif (isset ($config['dnsmasq']['enable'])) {
1170
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1171
				if ($syscfg['dnsserver'][0])
1172
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1173
				$mpdconf .= "\n";
1174
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1175
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1176
			}
1177

    
1178
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1179
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1180
				$acctport = $authport + 1;
1181
				$mpdconf .=<<<EOD
1182
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1183

    
1184
EOD;
1185
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1186
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1187
				$acctport = $authport + 1;
1188
				$mpdconf .=<<<EOD
1189
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret2']}" {$authport} {$acctport}
1190

    
1191
EOD;
1192
			}
1193
			$mpdconf .=<<<EOD
1194
	set radius retries 3
1195
	set radius timeout 10
1196
	set auth enable radius-auth
1197

    
1198
EOD;
1199

    
1200
				if (isset ($pptpdcfg['radius']['accounting'])) {
1201
					$mpdconf .=<<<EOD
1202
	set auth enable radius-acct
1203
	set radius acct-update 300
1204

    
1205
EOD;
1206
				}
1207
			}
1208

    
1209
			fwrite($fd, $mpdconf);
1210
			fclose($fd);
1211
			unset($mpdconf);
1212

    
1213
			/* write mpd.links */
1214
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1215
			if (!$fd) {
1216
				printf(gettext("Error: cannot open mpd.links in vpn_pptpd_configure().") . "\n");
1217
				return 1;
1218
			}
1219

    
1220
			$mpdlinks = "";
1221

    
1222
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1223
				$mpdlinks .=<<<EOD
1224

    
1225
pt{$i}:
1226
	set link type pptp
1227
	set pptp enable incoming
1228
	set pptp disable originate
1229
	set pptp disable windowing
1230

    
1231
EOD;
1232
			}
1233

    
1234
			fwrite($fd, $mpdlinks);
1235
			fclose($fd);
1236
			unset($mpdlinks);
1237

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

    
1245
			$mpdsecret = "";
1246

    
1247
			if (is_array($pptpdcfg['user'])) {
1248
				foreach ($pptpdcfg['user'] as $user) {
1249
					$pass = str_replace('\\', '\\\\', $user['password']);
1250
					$pass = str_replace('"', '\"', $pass);
1251
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1252
				}
1253
			}
1254

    
1255
			fwrite($fd, $mpdsecret);
1256
			fclose($fd);
1257
			unset($mpdsecret);
1258
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1259

    
1260
			vpn_netgraph_support();
1261

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

    
1265
			break;
1266

    
1267
		case 'redir' :
1268
			break;
1269
	}
1270

    
1271
	if ($g['booting'])
1272
		echo "done\n";
1273

    
1274
	return 0;
1275
}
1276

    
1277
function vpn_pppoes_configure() {
1278
	global $config;
1279

    
1280
	if (is_array($config['pppoes']['pppoe'])) {
1281
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1282
			vpn_pppoe_configure($pppoe);
1283
	}
1284
}
1285

    
1286
function vpn_pppoe_configure(&$pppoecfg) {
1287
	global $config, $g;
1288

    
1289
	$syscfg = $config['system'];
1290

    
1291
	/* create directory if it does not exist */
1292
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1293
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1294

    
1295
	if ($g['booting']) {
1296
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1297
			return 0;
1298

    
1299
		echo gettext("Configuring PPPoE VPN service... ");
1300
	} else {
1301
		/* kill mpd */
1302
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1303

    
1304
		/* wait for process to die */
1305
		sleep(2);
1306

    
1307
	}
1308

    
1309
	switch ($pppoecfg['mode']) {
1310

    
1311
		case 'server' :
1312

    
1313
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1314

    
1315
			if ($pppoecfg['paporchap'] == "chap")
1316
				$paporchap = "set link enable chap";
1317
			else
1318
				$paporchap = "set link enable pap";
1319

    
1320
			/* write mpd.conf */
1321
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1322
			if (!$fd) {
1323
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1324
				return 1;
1325
			}
1326
			$mpdconf = "\n\n";
1327
			$mpdconf .= "poes:\n";
1328

    
1329
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1330
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1331
			}
1332

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

    
1335
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1336

    
1337
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1338
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1339
				} else {
1340
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1341
				}
1342

    
1343
				$mpdconf .=<<<EOD
1344

    
1345
poes{$pppoecfg['pppoeid']}{$i}:
1346
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1347
	{$isssue_ip_type}
1348
	load pppoe_standard
1349

    
1350
EOD;
1351
			}
1352

    
1353
			$mpdconf .=<<<EOD
1354

    
1355
pppoe_standard:
1356
	set bundle no multilink
1357
	set bundle enable compression
1358
	set auth max-logins 1
1359
	set iface up-script /usr/local/sbin/vpn-linkup
1360
	set iface down-script /usr/local/sbin/vpn-linkdown
1361
	set iface idle 0
1362
	set iface disable on-demand
1363
	set iface disable proxy-arp
1364
	set iface enable tcpmssfix
1365
	set iface mtu 1500
1366
	set link no pap chap
1367
	{$paporchap}
1368
	set link keep-alive 60 180
1369
	set ipcp yes vjcomp
1370
	set ipcp no vjcomp
1371
	set link max-redial -1
1372
	set link mtu 1492
1373
	set link mru 1492
1374
	set ccp yes mpp-e40
1375
	set ccp yes mpp-e128
1376
	set ccp yes mpp-stateless
1377
	set link latency 1
1378
	#set ipcp dns 10.10.1.3
1379
	#set bundle accept encryption
1380

    
1381
EOD;
1382

    
1383
			if (!empty($pppoecfg['dns1'])) {
1384
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1385
				if (!empty($pppoecfg['dns2']))
1386
					$mpdconf .= " " . $pppoecfg['dns2'];
1387
				$mpdconf .= "\n";
1388
			} elseif (isset ($config['dnsmasq']['enable'])) {
1389
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1390
				if ($syscfg['dnsserver'][0])
1391
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1392
				$mpdconf .= "\n";
1393
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1394
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1395
			}
1396

    
1397
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1398
				$radiusport = "";
1399
				$radiusacctport = "";
1400
				if (isset($pppoecfg['radius']['server']['port']))
1401
					$radiusport = $pppoecfg['radius']['server']['port'];
1402
				if (isset($pppoecfg['radius']['server']['acctport']))
1403
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1404
				$mpdconf .=<<<EOD
1405
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1406
	set radius retries 3
1407
	set radius timeout 10
1408
	set auth enable radius-auth
1409

    
1410
EOD;
1411

    
1412
				if (isset ($pppoecfg['radius']['accounting'])) {
1413
					$mpdconf .=<<<EOD
1414
	set auth enable radius-acct
1415

    
1416
EOD;
1417
				}
1418
			}
1419

    
1420
			fwrite($fd, $mpdconf);
1421
			fclose($fd);
1422
			unset($mpdconf);
1423

    
1424
			/* write mpd.links */
1425
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.links", "w");
1426
			if (!$fd) {
1427
				printf(gettext("Error: cannot open mpd.links in vpn_pppoe_configure().") . "\n");
1428
				return 1;
1429
			}
1430

    
1431
			$mpdlinks = "";
1432

    
1433
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1434
				$mpdlinks .=<<<EOD
1435
			
1436
poes{$pppoecfg['pppoeid']}{$i}:
1437
	set phys type pppoe
1438
        set pppoe iface {$pppoe_interface}
1439
        set pppoe service "*"
1440
        set pppoe disable originate
1441
        set pppoe enable incoming
1442

    
1443
EOD;
1444
			}
1445

    
1446
			fwrite($fd, $mpdlinks);
1447
			fclose($fd);
1448
			unset($mpdlinks);
1449

    
1450
			if ($pppoecfg['username']) {
1451
				/* write mpd.secret */
1452
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1453
				if (!$fd) {
1454
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1455
					return 1;
1456
				}
1457

    
1458
				$mpdsecret = "\n\n";
1459

    
1460
				if (!empty($pppoecfg['username'])) {
1461
					$item = explode(" ", $pppoecfg['username']);
1462
					foreach($item as $userdata) {
1463
						$data = explode(":", $userdata);
1464
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1465
					}
1466
				}
1467

    
1468
				fwrite($fd, $mpdsecret);
1469
				fclose($fd);
1470
				unset($mpdsecret);
1471
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1472
			}
1473

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

    
1478
			/* Get support for netgraph(4) from the nic */
1479
			pfSense_ngctl_attach(".", $pppoe_interface);
1480
			/* fire up mpd */
1481
			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");
1482

    
1483
			break;
1484
	}
1485

    
1486
	if ($g['booting'])
1487
		echo gettext("done") . "\n";
1488

    
1489
	return 0;
1490
}
1491

    
1492
function vpn_l2tp_configure() {
1493
	global $config, $g;
1494

    
1495
	$syscfg = $config['system'];
1496
	$l2tpcfg = $config['l2tp'];
1497

    
1498
	/* create directory if it does not exist */
1499
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1500
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1501

    
1502
	if ($g['booting']) {
1503
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1504
			return 0;
1505

    
1506
		echo gettext("Configuring l2tp VPN service... ");
1507
	} else {
1508
		/* kill mpd */
1509
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1510

    
1511
		/* wait for process to die */
1512
		sleep(8);
1513

    
1514
	}
1515

    
1516
	/* make sure l2tp-vpn directory exists */
1517
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1518
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1519

    
1520
	switch ($l2tpcfg['mode']) {
1521

    
1522
		case 'server' :
1523
			if ($l2tpcfg['paporchap'] == "chap")
1524
				$paporchap = "set link enable chap";
1525
			else
1526
				$paporchap = "set link enable pap";
1527

    
1528
			/* write mpd.conf */
1529
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1530
			if (!$fd) {
1531
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1532
				return 1;
1533
			}
1534
			$mpdconf = "\n\n";
1535
			$mpdconf .=<<<EOD
1536
l2tps:
1537

    
1538
EOD;
1539

    
1540
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1541
				$mpdconf .= "	load l2tp{$i}\n";
1542
			}
1543

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

    
1546
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1547

    
1548
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1549
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1550
				} else {
1551
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1552
				}
1553

    
1554
				$mpdconf .=<<<EOD
1555

    
1556
l2tp{$i}:
1557
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1558
	{$isssue_ip_type}
1559
	load l2tp_standard
1560

    
1561
EOD;
1562
			}
1563

    
1564
			$mpdconf .=<<<EOD
1565

    
1566
l2tp_standard:
1567
        set bundle disable multilink
1568
        set bundle enable compression
1569
        set bundle yes crypt-reqd
1570
        set ipcp yes vjcomp
1571
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1572
        set ccp yes mppc
1573
        set iface disable on-demand
1574
        set iface enable proxy-arp
1575
	set iface up-script /usr/local/sbin/vpn-linkup
1576
	set iface down-script /usr/local/sbin/vpn-linkdown
1577
        set link yes acfcomp protocomp
1578
        set link no pap chap
1579
        set link enable chap
1580
        set link keep-alive 10 180
1581

    
1582
EOD;
1583

    
1584
			if (is_ipaddr($l2tpcfg['wins'])) {
1585
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1586
			}
1587
			if (is_ipaddr($l2tpcfg['dns1'])) {
1588
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1589
				if (is_ipaddr($l2tpcfg['dns2']))
1590
					$mpdconf .= " " . $l2tpcfg['dns2'];
1591
				$mpdconf .= "\n";
1592
			} elseif (isset ($config['dnsmasq']['enable'])) {
1593
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1594
				if ($syscfg['dnsserver'][0])
1595
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1596
				$mpdconf .= "\n";
1597
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1598
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1599
			}
1600

    
1601
			if (isset ($l2tpcfg['radius']['enable'])) {
1602
				$mpdconf .=<<<EOD
1603
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1604
	set radius retries 3
1605
	set radius timeout 10
1606
	set auth enable radius-auth
1607

    
1608
EOD;
1609

    
1610
				if (isset ($l2tpcfg['radius']['accounting'])) {
1611
					$mpdconf .=<<<EOD
1612
	set auth enable radius-acct
1613

    
1614
EOD;
1615
				}
1616
			}
1617

    
1618
			fwrite($fd, $mpdconf);
1619
			fclose($fd);
1620
			unset($mpdconf);
1621

    
1622
			/* write mpd.links */
1623
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1624
			if (!$fd) {
1625
				printf(gettext("Error: cannot open mpd.links in vpn_l2tp_configure().") . "\n");
1626
				return 1;
1627
			}
1628

    
1629
			$mpdlinks = "";
1630

    
1631
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1632
				$mpdlinks .=<<<EOD
1633

    
1634
l2tp{$i}:
1635
	set link type l2tp
1636
        set l2tp enable incoming
1637
        set l2tp disable originate
1638

    
1639
EOD;
1640
			if (!empty($l2tpcfg['secret']))
1641
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1642
			}
1643

    
1644
			fwrite($fd, $mpdlinks);
1645
			fclose($fd);
1646
			unset($mpdlinks);
1647

    
1648
			/* write mpd.secret */
1649
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1650
			if (!$fd) {
1651
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1652
				return 1;
1653
			}
1654

    
1655
			$mpdsecret = "\n\n";
1656

    
1657
			if (is_array($l2tpcfg['user'])) {
1658
				foreach ($l2tpcfg['user'] as $user)
1659
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1660
			}
1661

    
1662
			fwrite($fd, $mpdsecret);
1663
			fclose($fd);
1664
			unset($mpdsecret);
1665
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1666

    
1667
			vpn_netgraph_support();
1668

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

    
1672
			break;
1673

    
1674
		case 'redir' :
1675
			break;
1676
	}
1677

    
1678
	if ($g['booting'])
1679
		echo "done\n";
1680

    
1681
	return 0;
1682
}
1683

    
1684
/* Walk the tunnels for hostname endpoints. If the hostnames 
1685
 * resolve to a different IP now compared to the DNS cache
1686
 * we reload the policies if the endpoint has changed */
1687
function vpn_ipsec_refresh_policies() {
1688
	global $config;
1689
	global $g;
1690

    
1691
	$ipseccfg = $config['ipsec'];
1692
	$a_phase1 = $config['ipsec']['phase1'];
1693
	$a_phase2 = $config['ipsec']['phase2'];
1694

    
1695
	if (isset($ipseccfg['disable'])) {
1696
		return true;
1697
	}
1698

    
1699
	/* Walk the Ipsec tunnel array */
1700
	if (!is_array($a_phase1) || (!count($a_phase1)))
1701
		return;
1702

    
1703
	foreach ($a_phase1 as $phase1) {
1704
		if (isset($phase1['disabled']))
1705
			continue;
1706
		if (is_ipaddr($phase1['remote-gateway']))
1707
			continue;
1708
		if (!is_ipaddr($phase1['remote-gateway'])) {
1709
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1710
			$dnscache = trim($dnscache);
1711
			/* we should have the old IP addresses in the dnscache now */
1712
			if(!empty($dnscache)) {
1713
				$oldphase1 = $phase1;
1714
				$oldphase1['remote-gateway'] = $dnscache;
1715
				/* now we need to find all tunnels for this host */
1716
				if (!is_array($a_phase2) || (!count($a_phase2)))
1717
					continue;
1718
				foreach ($a_phase2 as $phase2) {
1719
					if ($phase2['ikeid'] == $phase1['ikeid'])
1720
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1721
				}
1722
			}
1723
		}
1724
	}
1725

    
1726
	/* process all generated temporary spd.conf files */
1727
	$tmpfiles = glob("{$g['tmp_path']}/spd.conf.reload.*");
1728
	foreach($tmpfiles as $tmpfile) {
1729
		$ret = mwexec("/usr/local/sbin/setkey -f {$tmpfile} 2>&1", false);
1730
		if ($ret == 0)
1731
			unlink_if_exists($tmpfile);
1732
		else {
1733
			$tmpfile = basename($tmpfile);
1734
			@rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1735
		}
1736
	}
1737
}
1738

    
1739
/* remove SPD polices */
1740
function remove_tunnel_spd_policy($phase1,$phase2) {
1741
	global $config;
1742
	global $g;
1743

    
1744
	if (!$phase1 || !$phase2)
1745
		return false;
1746

    
1747
	if (isset($phase1['mobile']))
1748
		return false;
1749

    
1750
	$spdconf = "";
1751
	$ep = ipsec_get_phase1_src($phase1);
1752
	$gw = trim($phase1['remote-gateway']);
1753
	$sad_arr = ipsec_dump_sad();
1754
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1755

    
1756
	if (!empty($phase2['natlocalid']))
1757
		$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid']);
1758
	else
1759
		$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1760

    
1761
	if ($phase2['mode'] == "tunnel6")
1762
		$family = "-6";
1763
	else
1764
		$family = "-4";
1765

    
1766
	$spdconf .= "spddelete {$family} {$local_subnet} " .
1767
		"{$remote_subnet} any -P out ipsec " .
1768
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1769
		"{$gw}/unique;\n";
1770

    
1771
	$spdconf .= "spddelete {$family} {$remote_subnet} " .
1772
		"{$local_subnet} any -P in ipsec " .
1773
		"{$phase2['protocol']}/tunnel/{$gw}-" .
1774
		"{$ep}/unique;\n";
1775

    
1776
	/* zap any existing SA entries */
1777
	foreach($sad_arr as $sad) {
1778
		if(($sad['dst'] == $ep) && ($sad['src'] == $gw))
1779
			$spdconf .= "delete {$family} {$ep} {$gw} {$phase2['protocol']} 0x{$sad['spi']};\n";
1780
		if(($sad['src'] == $ep) && ($sad['dst'] == $_gw))
1781
			$spdconf .= "delete {$family} {$gw} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1782
	}
1783

    
1784
	log_error(sprintf(gettext("Removing SPDs from tunnel gw '%1\$s'. Local Subnet '%2\$s' and Remote Subnet '%3\$s'. Reloading policy"),$phase1['remote-gateway'],$local_subnet,$remote_subnet));
1785

    
1786
	$now = time();
1787
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1788
	/* generate temporary spd.conf */
1789
	@file_put_contents($spdfile, $spdconf);
1790
	unset($spdconf);
1791

    
1792
	return true;
1793
}
1794

    
1795
/* reloads the tunnel configuration for a tunnel item
1796
 * Will remove and add SPD polices */
1797
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1798
	global $config;
1799
	global $g;
1800

    
1801
	/* if we are not passed a old tunnel array we create one */
1802
	if(empty($old_phase1)) {
1803
		$old_phase1 = $phase1;
1804
	}
1805
	if(empty($old_phase2)) {
1806
		$old_phase2 = $phase2;
1807
	}
1808

    
1809
	$sad_arr = ipsec_dump_sad();
1810

    
1811
	$ep = ipsec_get_phase1_src($phase1);
1812
	$phase2['localid']['mode'] = $phase2['mode'];
1813
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1814
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1815

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

    
1819
	$old_ep = ipsec_get_phase1_src($old_phase1);
1820
	$old_phase2['localid']['mode'] = $old_phase2['mode'];
1821
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1822
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1823

    
1824
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1825
	 * try to resolve it now and add it to the list for filterdns */
1826
	$rgip = "";
1827
	if (!is_ipaddr($phase1['remote-gateway'])) {
1828
		if(! $g['booting']) {
1829
			$rgip = resolve_retry($phase1['remote-gateway']);
1830
			add_hostname_to_watch($phase1['remote-gateway']);
1831
		} else {
1832
			add_hostname_to_watch($phase1['remote-gateway']);
1833
		}
1834
		if (!is_ipaddr($rgip)) {
1835
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1836
			return false;
1837
		}
1838
	} else {
1839
		$rgip = $phase1['remote-gateway'];
1840
	}
1841
	if (!$ep) {
1842
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1843
		return false;
1844
	}
1845

    
1846
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1847
		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));
1848
	}
1849
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1850
		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));
1851
	}
1852

    
1853
	$spdconf = "";
1854
	/* Delete old SPD policies if there are changes between the old and new */
1855
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1856
		if($old_phase2['mode'] == "tunnel6")
1857
			$family = "-6";
1858
		else
1859
			$family = "-4";
1860

    
1861
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1862
			"{$old_remote_subnet} any -P out ipsec " .
1863
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1864
			"{$old_gw}/unique;\n";
1865
		if (!empty($old_phase2['natlocalid']))
1866
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid']);
1867
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1868
			"{$old_local_subnet} any -P in ipsec " .
1869
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1870
			"{$old_ep}/unique;\n";
1871

    
1872
		/* zap any existing SA entries */
1873
		foreach($sad_arr as $sad) {
1874
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1875
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1876
			}
1877
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1878
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1879
			}
1880
		}
1881
	}
1882

    
1883
	if($phase2['mode'] == "tunnel6")
1884
		$family = "-6";
1885
	else
1886
		$family = "-4";
1887

    
1888
	/* Create new SPD entries for the new configuration */
1889
	/* zap any existing SA entries beforehand */
1890
	foreach($sad_arr as $sad) {
1891
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1892
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1893
		}
1894
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1895
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1896
		}
1897
	}
1898
	/* add new SPD policies to replace them */
1899
	if (!isset($phase1['disabled'])) {
1900
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1901
			"{$remote_subnet} any -P out ipsec " .
1902
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1903
			"{$rgip}/unique;\n";
1904

    
1905
		if (!empty($phase2['natlocalid']))
1906
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid']);
1907
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1908
			"{$local_subnet} any -P in ipsec " .
1909
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1910
			"{$ep}/unique;\n";
1911
	}
1912

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

    
1915
	$now = time();
1916
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1917
	/* generate temporary spd.conf */
1918
	@file_put_contents($spdfile, $spdconf);
1919
	unset($spdconf);
1920
	return true;
1921
}
1922

    
1923
function vpn_ipsec_configure_preferoldsa() {
1924
	global $config;
1925
	if(isset($config['ipsec']['preferoldsa']))
1926
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1927
	else
1928
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1929
}
1930

    
1931
?>
(58-58/67)