Project

General

Profile

Download (56.8 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
require_once("ipsec.inc");
45

    
46
/* include all configuration functions */
47

    
48
function vpn_ipsec_failover_configure() {
49
	global $config, $g;
50

    
51

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

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

    
75
		if(is_process_running("sasyncd"))
76
			mwexec("killall sasyncd", true);
77

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

    
83
function vpn_ipsec_configure($ipchg = false)
84
{
85
	global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos;
86

    
87
	if ($g['platform'] == 'jail')
88
		return;
89

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

    
94
	vpn_ipsec_configure_preferoldsa();
95

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

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

    
108
		/* kill racoon forcefully */
109
		if (is_process_running("racoon"))
110
			mwexec("/usr/bin/killall -9 racoon", true);
111

    
112
		/* wait for racoon process to die */
113
		sleep(2);
114

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

    
119
		/* disallow IPSEC, it is off */
120
		mwexec("/sbin/ifconfig enc0 down");
121
		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
122

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

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

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

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

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

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

    
256
		$pskconf = "";
257

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

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

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

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

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

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

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

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

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

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

    
305
		@file_put_contents("{$g['varetc_path']}/ipsec/psk.txt", $pskconf);
306
		chmod("{$g['varetc_path']}/ipsec/psk.txt", 0600);
307
		unset($pskconf);
308

    
309
		/* begin racoon.conf */
310
		$racoonconf = "";
311
		$peerid_verify = "";
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, $ph2ent['mode']);
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
						if (isset($ph1ent['verify_identifier']))
612
							$peerid_verify = "verify_identifier on;";
613
					}
614

    
615
					/* add remote section to configuration */
616

    
617
					$racoonconf .=<<<EOD
618

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

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

    
648
EOD;
649
				}
650
				/* end remote */
651
			}
652
			/* end remote sections */
653

    
654
			/* begin sainfo sections */
655
			if (is_array($a_phase2) && count($a_phase2)) {
656

    
657
				/* begin sainfo */
658
				foreach ($a_phase2 as $ph2ent) {
659

    
660
					$ikeid = $ph2ent['ikeid'];
661

    
662
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
663
						continue;
664

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

    
668
					if (isset($ph2ent['disabled']))
669
						continue;
670

    
671
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
672
						continue;
673

    
674
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
675

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

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

    
712
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
713
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
714
						} else
715
							$remoteid_spec = "anonymous";
716

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

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

    
737
					if($ph2ent['protocol'] == 'esp') {
738

    
739
						$ealgos = '';
740

    
741
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
742

    
743
							$ealg_id = $ealg['name'];
744
							$ealg_kl = $ealg['keylen'];
745

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

    
781
						$ealgosline = "encryption_algorithm {$ealgos};";
782

    
783
					} else {
784

    
785
						$ealgosline = "encryption_algorithm null_enc;";
786
					}
787

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

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

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

    
804
					/* add sainfo section to configuration */
805

    
806
					$racoonconf .=<<<EOD
807

    
808
sainfo {$localid_spec} {$remoteid_spec}
809
{
810
	remoteid {$ikeid};
811
	{$ealgosline}
812
	{$halgosline}
813
	{$pfsline}
814
	{$lifeline}
815
	compression_algorithm deflate;
816
}
817

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

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

    
851
			foreach ($a_phase2 as $ph2ent) {
852

    
853
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
854
					continue;
855

    
856
				if (isset($ph1ent['mobile']))
857
					continue;
858

    
859
				if (isset($ph1ent['disabled']))
860
					continue;
861

    
862
				if (isset($ph2ent['disabled']))
863
					continue;
864

    
865
				$ep = ipsec_get_phase1_src($ph1ent);
866
				if (!$ep)
867
					continue;
868

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

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

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

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

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

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

    
898
				} else {
899

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

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

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

    
909
				}
910

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

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

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

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

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

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

    
991
		vpn_ipsec_failover_configure();
992

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

    
996
		return count($filterdns_list);
997
	}
998
}
999

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

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

    
1011
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1012
		$found = false;
1013
		foreach ($ipseccfg['phase1'] as $ipsec) {
1014
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1015
				$found = true;
1016
				break;
1017
			}
1018
		}
1019
		if (!$found) {
1020
			log_error(sprintf(gettext("Ignoring IPsec racoon daemon reload since there are no tunnels on interface %s"), $interface));
1021
			return;
1022
		}
1023
	}
1024

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

    
1028
	/* wait for process to die */
1029
	sleep(4);
1030

    
1031
	/* kill racoon forcefully */
1032
	if (is_process_running("racoon"))
1033
		mwexec("/usr/bin/killall -9 racoon", true);
1034

    
1035
	/* wait for flushing to finish */
1036
	sleep(1);
1037

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

    
1045
/* master setup for vpn (mpd) */
1046
function vpn_setup() {
1047
	global $g;
1048

    
1049
	if ($g['platform'] == 'jail')
1050
		return;
1051

    
1052
	/* start pptpd */
1053
	vpn_pptpd_configure();
1054

    
1055
	/* start pppoe server */
1056
	vpn_pppoes_configure();
1057

    
1058
	/* setup l2tp */
1059
	vpn_l2tp_configure();
1060
}
1061

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

    
1073
function vpn_pptpd_configure() {
1074
	global $config, $g;
1075

    
1076
	$syscfg = $config['system'];
1077
	$pptpdcfg = $config['pptpd'];
1078

    
1079
	if ($g['booting']) {
1080
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1081
			return 0;
1082

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

    
1088
		/* wait for process to die */
1089
		sleep(3);
1090

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

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

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

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

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

    
1120
			$mpdconf = <<<EOD
1121
pptps:
1122

    
1123
EOD;
1124

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

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

    
1131
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1132

    
1133
				$mpdconf .= <<<EOD
1134

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

    
1140
EOD;
1141
			}
1142

    
1143
			$mpdconf .=<<<EOD
1144

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

    
1165
EOD;
1166

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

    
1172
EOD;
1173
			}
1174

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

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

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

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

    
1205
EOD;
1206
			}
1207
			$mpdconf .=<<<EOD
1208
	set radius retries 3
1209
	set radius timeout 10
1210
	set auth enable radius-auth
1211

    
1212
EOD;
1213

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

    
1219
EOD;
1220
				}
1221
			}
1222

    
1223
			fwrite($fd, $mpdconf);
1224
			fclose($fd);
1225
			unset($mpdconf);
1226

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

    
1234
			$mpdlinks = "";
1235

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

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

    
1245
EOD;
1246
			}
1247

    
1248
			fwrite($fd, $mpdlinks);
1249
			fclose($fd);
1250
			unset($mpdlinks);
1251

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

    
1259
			$mpdsecret = "";
1260

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

    
1269
			fwrite($fd, $mpdsecret);
1270
			fclose($fd);
1271
			unset($mpdsecret);
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
			unset($mpdconf);
1437

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

    
1445
			$mpdlinks = "";
1446

    
1447
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1448
				$mpdlinks .=<<<EOD
1449

    
1450
poes{$pppoecfg['pppoeid']}{$i}:
1451
	set phys type pppoe
1452
	set pppoe iface {$pppoe_interface}
1453
	set pppoe service "*"
1454
	set pppoe disable originate
1455
	set pppoe enable incoming
1456

    
1457
EOD;
1458
			}
1459

    
1460
			fwrite($fd, $mpdlinks);
1461
			fclose($fd);
1462
			unset($mpdlinks);
1463

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

    
1472
				$mpdsecret = "\n\n";
1473

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

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

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

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

    
1497
			break;
1498
	}
1499

    
1500
	if ($g['booting'])
1501
		echo gettext("done") . "\n";
1502

    
1503
	return 0;
1504
}
1505

    
1506
function vpn_l2tp_configure() {
1507
	global $config, $g;
1508

    
1509
	$syscfg = $config['system'];
1510
	$l2tpcfg = $config['l2tp'];
1511

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

    
1516
	if ($g['booting']) {
1517
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1518
			return 0;
1519

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

    
1525
		/* wait for process to die */
1526
		sleep(8);
1527

    
1528
	}
1529

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

    
1534
	switch ($l2tpcfg['mode']) {
1535

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

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

    
1552
EOD;
1553

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

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

    
1560
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1561

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

    
1568
				$mpdconf .=<<<EOD
1569

    
1570
l2tp{$i}:
1571
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1572
	{$isssue_ip_type}
1573
	load l2tp_standard
1574

    
1575
EOD;
1576
			}
1577

    
1578
			$mpdconf .=<<<EOD
1579

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

    
1596
EOD;
1597

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

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

    
1622
EOD;
1623

    
1624
				if (isset ($l2tpcfg['radius']['accounting'])) {
1625
					$mpdconf .=<<<EOD
1626
	set auth enable radius-acct
1627

    
1628
EOD;
1629
				}
1630
			}
1631

    
1632
			fwrite($fd, $mpdconf);
1633
			fclose($fd);
1634
			unset($mpdconf);
1635

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

    
1643
			$mpdlinks = "";
1644

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

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

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

    
1658
			fwrite($fd, $mpdlinks);
1659
			fclose($fd);
1660
			unset($mpdlinks);
1661

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

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

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

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

    
1681
			vpn_netgraph_support();
1682

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

    
1686
			break;
1687

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

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

    
1695
	return 0;
1696
}
1697

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

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

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

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

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

    
1738
	/* process all generated temporary spd.conf files */
1739
	$tmpfiles = glob("{$g['tmp_path']}/spd.conf.reload.*");
1740
	foreach($tmpfiles as $tmpfile) {
1741
		$ret = mwexec("/usr/local/sbin/setkey -f {$tmpfile} 2>&1", false);
1742
		if ($ret == 0)
1743
			unlink_if_exists($tmpfile);
1744
		else {
1745
			$tmpfile = basename($tmpfile);
1746
			@rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1747
		}
1748
	}
1749
}
1750

    
1751
/* remove SPD polices */
1752
function remove_tunnel_spd_policy($phase1,$phase2) {
1753
	global $config;
1754
	global $g;
1755

    
1756
	if (!$phase1 || !$phase2)
1757
		return false;
1758

    
1759
	if (isset($phase1['mobile']))
1760
		return false;
1761

    
1762
	$spdconf = "";
1763
	$ep = ipsec_get_phase1_src($phase1);
1764
	$gw = trim($phase1['remote-gateway']);
1765
	$sad_arr = ipsec_dump_sad();
1766
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1767

    
1768
	if (!empty($phase2['natlocalid']))
1769
		$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1770
	else
1771
		$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1772

    
1773
	if ($phase2['mode'] == "tunnel6")
1774
		$family = "-6";
1775
	else
1776
		$family = "-4";
1777

    
1778
	$spdconf .= "spddelete {$family} {$local_subnet} " .
1779
		"{$remote_subnet} any -P out ipsec " .
1780
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1781
		"{$gw}/unique;\n";
1782

    
1783
	$spdconf .= "spddelete {$family} {$remote_subnet} " .
1784
		"{$local_subnet} any -P in ipsec " .
1785
		"{$phase2['protocol']}/tunnel/{$gw}-" .
1786
		"{$ep}/unique;\n";
1787

    
1788
	/* zap any existing SA entries */
1789
	foreach($sad_arr as $sad) {
1790
		if(($sad['dst'] == $ep) && ($sad['src'] == $gw))
1791
			$spdconf .= "delete {$family} {$ep} {$gw} {$phase2['protocol']} 0x{$sad['spi']};\n";
1792
		if(($sad['src'] == $ep) && ($sad['dst'] == $_gw))
1793
			$spdconf .= "delete {$family} {$gw} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1794
	}
1795

    
1796
	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));
1797

    
1798
	$now = time();
1799
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1800
	/* generate temporary spd.conf */
1801
	@file_put_contents($spdfile, $spdconf);
1802
	unset($spdconf);
1803

    
1804
	return true;
1805
}
1806

    
1807
/* reloads the tunnel configuration for a tunnel item
1808
 * Will remove and add SPD polices */
1809
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1810
	global $config;
1811
	global $g;
1812

    
1813
	/* if we are not passed a old tunnel array we create one */
1814
	if(empty($old_phase1)) {
1815
		$old_phase1 = $phase1;
1816
	}
1817
	if(empty($old_phase2)) {
1818
		$old_phase2 = $phase2;
1819
	}
1820

    
1821
	$sad_arr = ipsec_dump_sad();
1822

    
1823
	$ep = ipsec_get_phase1_src($phase1);
1824
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1825
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1826

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

    
1830
	$old_ep = ipsec_get_phase1_src($old_phase1);
1831
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid'], false, $old_phase2['mode']);
1832
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid'], false, $old_phase2['mode']);
1833

    
1834
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1835
	 * try to resolve it now and add it to the list for filterdns */
1836
	$rgip = "";
1837
	if (!is_ipaddr($phase1['remote-gateway'])) {
1838
		if(! $g['booting']) {
1839
			$rgip = resolve_retry($phase1['remote-gateway']);
1840
			add_hostname_to_watch($phase1['remote-gateway']);
1841
		} else {
1842
			add_hostname_to_watch($phase1['remote-gateway']);
1843
		}
1844
		if (isset($phase1['mobile'])) {
1845
			/* Don't log anything here, it's normal and we should skip it. */
1846
			return false;
1847
		} elseif (!is_ipaddr($rgip)) {
1848
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1849
			return false;
1850
		}
1851
	} else {
1852
		$rgip = $phase1['remote-gateway'];
1853
	}
1854
	if (!$ep) {
1855
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1856
		return false;
1857
	}
1858

    
1859
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1860
		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));
1861
	}
1862
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1863
		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));
1864
	}
1865

    
1866
	$spdconf = "";
1867
	/* Delete old SPD policies if there are changes between the old and new */
1868
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1869
		if($old_phase2['mode'] == "tunnel6")
1870
			$family = "-6";
1871
		else
1872
			$family = "-4";
1873

    
1874
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1875
			"{$old_remote_subnet} any -P out ipsec " .
1876
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1877
			"{$old_gw}/unique;\n";
1878
		if (!empty($old_phase2['natlocalid']))
1879
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid'], false, $old_phase2['mode']);
1880
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1881
			"{$old_local_subnet} any -P in ipsec " .
1882
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1883
			"{$old_ep}/unique;\n";
1884

    
1885
		/* zap any existing SA entries */
1886
		foreach($sad_arr as $sad) {
1887
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1888
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1889
			}
1890
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1891
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1892
			}
1893
		}
1894
	}
1895

    
1896
	if($phase2['mode'] == "tunnel6")
1897
		$family = "-6";
1898
	else
1899
		$family = "-4";
1900

    
1901
	/* Create new SPD entries for the new configuration */
1902
	/* zap any existing SA entries beforehand */
1903
	foreach($sad_arr as $sad) {
1904
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1905
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1906
		}
1907
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1908
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1909
		}
1910
	}
1911
	/* add new SPD policies to replace them */
1912
	if (!isset($phase1['disabled']) && !isset($phase2['disabled'])) {
1913
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1914
			"{$remote_subnet} any -P out ipsec " .
1915
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1916
			"{$rgip}/unique;\n";
1917

    
1918
		if (!empty($phase2['natlocalid']))
1919
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1920
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1921
			"{$local_subnet} any -P in ipsec " .
1922
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1923
			"{$ep}/unique;\n";
1924
	}
1925

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

    
1928
	$now = time();
1929
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1930
	/* generate temporary spd.conf */
1931
	@file_put_contents($spdfile, $spdconf);
1932
	unset($spdconf);
1933
	/* remove static route to old gw */
1934
	if (is_ipaddr($old_gw))
1935
		mwexec("/sbin/route delete {$old_gw}", true);
1936
	return true;
1937
}
1938

    
1939
function vpn_ipsec_configure_preferoldsa() {
1940
	global $config;
1941
	if(isset($config['ipsec']['preferoldsa']))
1942
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1943
	else
1944
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1945
}
1946

    
1947
?>
(57-57/66)