Project

General

Profile

Download (60 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * vpn.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2019 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2008 Shrew Soft Inc
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
 * Licensed under the Apache License, Version 2.0 (the "License");
15
 * you may not use this file except in compliance with the License.
16
 * You may obtain a copy of the License at
17
 *
18
 * http://www.apache.org/licenses/LICENSE-2.0
19
 *
20
 * Unless required by applicable law or agreed to in writing, software
21
 * distributed under the License is distributed on an "AS IS" BASIS,
22
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
 * See the License for the specific language governing permissions and
24
 * limitations under the License.
25
 */
26

    
27
require_once("ipsec.inc");
28
require_once("filter.inc");
29
require_once("auth.inc");
30

    
31
function vpn_update_daemon_loglevel($category, $level) {
32
	global $ipsec_log_cats, $ipsec_log_sevs;
33

    
34
	if (in_array($category, array_keys($ipsec_log_cats), true) && in_array(intval($level), array_keys($ipsec_log_sevs), true)) {
35

    
36
		/* if you're setting to -1, need to add "--" to args */
37
		$argterm = "";
38
		if ($level == "-1") {
39
			$argterm = "--";
40
		}
41

    
42
		mwexec("/usr/local/sbin/ipsec stroke loglevel {$category} {$argterm} {$level}");
43
	}
44
}
45

    
46
function vpn_logging_cfgtxt() {
47
	global $config, $ipsec_log_cats, $ipsec_log_sevs;
48

    
49
	$cfgtext = array();
50
	$log_levels = ipsec_get_loglevels();
51
	foreach (array_keys($ipsec_log_cats) as $cat) {
52
		if (is_numeric($log_levels[$cat]) &&
53
		    in_array(intval($log_levels[$cat]), array_keys($ipsec_log_sevs), true)) {
54
			$cfgtext[] = "${cat} = {$log_levels[$cat]}";
55
		}
56
	}
57

    
58
	return $cfgtext;
59
}
60

    
61
/* include all configuration functions */
62
function vpn_ipsec_convert_to_modp($index) {
63

    
64
	$conversion = "";
65
	switch ($index) {
66
		case '1':
67
			$conversion = "modp768";
68
			break;
69
		case '2':
70
			$conversion = "modp1024";
71
			break;
72
		case '5':
73
			$conversion = "modp1536";
74
			break;
75
		case '14':
76
			$conversion = "modp2048";
77
			break;
78
		case '15':
79
			$conversion = "modp3072";
80
			break;
81
		case '16':
82
			$conversion = "modp4096";
83
			break;
84
		case '17':
85
			$conversion = "modp6144";
86
			break;
87
		case '18':
88
			$conversion = "modp8192";
89
			break;
90
		case '19':
91
			$conversion = "ecp256";
92
			break;
93
		case '20':
94
			$conversion = "ecp384";
95
			break;
96
		case '21':
97
			$conversion = "ecp521";
98
			break;
99
		case '22':
100
			$conversion = "modp1024s160";
101
			break;
102
		case '23':
103
			$conversion = "modp2048s224";
104
			break;
105
		case '24':
106
			$conversion = "modp2048s256";
107
			break;
108
		case '28':
109
			$conversion = "ecp256bp";
110
			break;
111
		case '29':
112
			$conversion = "ecp384bp";
113
			break;
114
		case '30':
115
			$conversion = "ecp512bp";
116
			break;
117
	}
118

    
119
	return $conversion;
120
}
121

    
122
function vpn_ipsec_configure($restart = false) {
123
	global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos, $ipsec_idhandling;
124

    
125
	$ipsecstartlock = lock('ipsec', LOCK_EX);
126

    
127
	/* get the automatic ping_hosts.sh ready */
128
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
129
	touch("{$g['vardb_path']}/ipsecpinghosts");
130
	$ipsecpinghostsactive = false;
131

    
132
	/* service may have been enabled, disabled, or otherwise changed in a way requiring rule updates */
133
	filter_configure();
134

    
135
	$syscfg = $config['system'];
136
	$ipseccfg = $config['ipsec'];
137

    
138
	/* Configure asynchronous crypto. See https://redmine.pfsense.org/issues/8772 */
139
	set_sysctl(array('net.inet.ipsec.async_crypto' => (int) (isset($ipseccfg['async_crypto']) && ($ipseccfg['async_crypto'] == "enabled"))));
140

    
141
	if (!ipsec_enabled()) {
142
		/* try to stop charon */
143
		mwexec("/usr/local/sbin/ipsec stop");
144
		/* Stop dynamic monitoring */
145
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
146

    
147
		/* wait for process to die */
148
		sleep(2);
149

    
150
		/* IPSEC is off, shutdown enc interface.*/
151
		mwexec("/sbin/ifconfig enc0 down");
152

    
153
		unlock($ipsecstartlock);
154
		return 0;
155
	}
156

    
157
	$a_phase1 = $config['ipsec']['phase1'];
158
	$a_phase2 = $config['ipsec']['phase2'];
159
	$a_client = $config['ipsec']['client'];
160

    
161
	$certpath = "{$g['varetc_path']}/ipsec/ipsec.d/certs";
162
	$capath = "{$g['varetc_path']}/ipsec/ipsec.d/cacerts";
163
	$keypath = "{$g['varetc_path']}/ipsec/ipsec.d/private";
164
	$crlpath = "{$g['varetc_path']}/ipsec/ipsec.d/crls";
165

    
166
	mwexec("/sbin/ifconfig enc0 up");
167
	$ipsec_vti_cleanup_ifs = array();
168

    
169
	/* needed for config files */
170
	safe_mkdir("{$g['varetc_path']}/ipsec");
171
	safe_mkdir("{$g['varetc_path']}/ipsec/ipsec.d");
172

    
173
	// delete these paths first to ensure old CAs, certs and CRLs aren't left behind. redmine #5238
174
	rmdir_recursive($capath);
175
	rmdir_recursive($keypath);
176
	rmdir_recursive($crlpath);
177
	rmdir_recursive($certpath);
178

    
179
	safe_mkdir($capath);
180
	safe_mkdir($keypath);
181
	safe_mkdir($crlpath);
182
	safe_mkdir($certpath);
183
	safe_mkdir("{$g['varetc_path']}/ipsec/ipsec.d/aacerts");
184
	safe_mkdir("{$g['varetc_path']}/ipsec/ipsec.d/acerts");
185
	safe_mkdir("{$g['varetc_path']}/ipsec/ipsec.d/ocspcerts");
186
	safe_mkdir("{$g['varetc_path']}/ipsec/ipsec.d/reqs");
187

    
188
	if (!file_exists("/usr/local/etc/ipsec.d") ||
189
	    !is_link("/usr/local/etc/ipsec.d")) {
190
		if (file_exists("/usr/local/etc/ipsec.d")) {
191
			rmdir_recursive("/usr/local/etc/ipsec.d");
192
		}
193
		@symlink("{$g['varetc_path']}/ipsec/ipsec.d",
194
		    "/usr/local/etc/ipsec.d");
195
	}
196
	if (!file_exists("{$g['varetc_path']}/etc/strongswan.d") ||
197
	    !is_link("{$g['varetc_path']}/etc/strongswan.d")) {
198
		if (is_link("{$g['varetc_path']}/etc/strongswan.d")) {
199
			@unlink("{$g['varetc_path']}/etc/strongswan.d");
200
		} else {
201
			rmdir_recursive("{$g['varetc_path']}/etc/strongswan.d");
202
		}
203
		@symlink("/usr/local/etc/strongswan.d",
204
		    "{$g['varetc_path']}/ipsec/strongswan.d");
205
	}
206
	if (!file_exists("/usr/local/etc/strongswan.conf") ||
207
	    !is_link("/usr/local/etc/strongswan.conf")) {
208
		@unlink("/usr/local/etc/strongswan.conf");
209
		@symlink("{$g['varetc_path']}/ipsec/strongswan.conf",
210
		    "/usr/local/etc/strongswan.conf");
211
	}
212
	if (!file_exists("/usr/local/etc/ipsec.conf") ||
213
	    !is_link("/usr/local/etc/ipsec.conf")) {
214
		@unlink("/usr/local/etc/ipsec.conf");
215
		@symlink("{$g['varetc_path']}/ipsec/ipsec.conf",
216
		    "/usr/local/etc/ipsec.conf");
217
	}
218

    
219
	if (platform_booting()) {
220
		echo gettext("Configuring IPsec VPN... ");
221
	}
222

    
223
	/* resolve all local, peer addresses and setup pings */
224
	$ipmap = array();
225
	$rgmap = array();
226
	$filterdns_list = array();
227
	$aggressive_mode_psk = false;
228
	unset($iflist);
229
	$ifacesuse = array();
230
	$mobile_ipsec_auth = "";
231
	if (is_array($a_phase1) && count($a_phase1)) {
232

    
233
		$ipsecpinghosts = array();
234
		/* step through each phase1 entry */
235
		foreach ($a_phase1 as $ph1ent) {
236
			if (isset($ph1ent['disabled'])) {
237
				continue;
238
			}
239

    
240
			if (substr($ph1ent['interface'], 0, 4) == "_vip") {
241
				$vpninterface = get_configured_vip_interface($ph1ent['interface']);
242
				$ifacesuse[] = get_real_interface($vpninterface);
243
			} else {
244
				$vpninterface = get_failover_interface($ph1ent['interface']);
245
				if (substr($vpninterface, 0, 4) == "_vip") {
246
					$vpninterface = get_configured_vip_interface($vpninterface);
247
					$ifacesuse[] = get_real_interface($vpninterface);
248
				} elseif (!empty($vpninterface)) {
249
					$ifacesuse[] = $vpninterface;
250
				}
251
			}
252

    
253
			if ($ph1ent['mode'] == "aggressive" && ($ph1ent['authentication_method'] == "pre_shared_key" || $ph1ent['authentication_method'] == "xauth_psk_server")) {
254
				$aggressive_mode_psk = true;
255
			}
256

    
257
			$ikeid = $ph1ent['ikeid'];
258

    
259
			$ep = ipsec_get_phase1_src($ph1ent);
260
			/* When automatically guessing, use the first address. */
261
			$ep  = explode(',', $ep);
262
			$ep  = $ep[0];
263
			if (!is_ipaddr($ep)) {
264
				log_error(sprintf(gettext("IPsec ERROR: Could not find phase 1 source for connection %s. Omitting from configuration file."), $ph1ent['descr']));
265
				continue;
266
			}
267

    
268
			if (!in_array($ep, $ipmap)) {
269
				$ipmap[] = $ep;
270
			}
271

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

    
275
			if (isset ($ph1ent['mobile'])) {
276
				$mobile_ipsec_auth = $ph1ent['authentication_method'];
277
				continue;
278
			}
279

    
280
			$rg = $ph1ent['remote-gateway'];
281

    
282
			if (!is_ipaddr($rg)) {
283
				$filterdns_list[] = "{$rg}";
284
				add_hostname_to_watch($rg);
285
				if (!platform_booting()) {
286
					$rg = resolve_retry($rg);
287
				}
288
				if (!is_ipaddr($rg)) {
289
					continue;
290
				}
291
			}
292
			if (array_search($rg, $rgmap)) {
293
				log_error(sprintf(gettext("The remote gateway %s already exists on another phase 1 entry"), $rg));
294
				continue;
295
			}
296
			$rgmap[$ph1ent['remote-gateway']] = $rg;
297

    
298
			$is_vti = false;
299
			if (is_array($a_phase2)) {
300
				/* step through each phase2 entry */
301
				foreach ($a_phase2 as $ph2ent) {
302
					if ($ph2ent['mode'] == 'vti') {
303
						$is_vti = true;
304
					}
305
					if (isset($ph2ent['disabled'])) {
306
						continue;
307
					}
308

    
309
					if ($ikeid != $ph2ent['ikeid']) {
310
						continue;
311
					}
312

    
313
					/* add an ipsec pinghosts entry */
314
					if ($ph2ent['pinghost']) {
315
						if (!is_array($iflist)) {
316
							$iflist = get_configured_interface_list();
317
						}
318
						$srcip = null;
319
						$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
320
						if (is_ipaddrv6($ph2ent['pinghost'])) {
321
							foreach ($iflist as $ifent => $ifname) {
322
								$interface_ip = get_interface_ipv6($ifent);
323
								if (!is_ipaddrv6($interface_ip)) {
324
									continue;
325
								}
326
								if (ip_in_subnet($interface_ip, $local_subnet)) {
327
									$srcip = $interface_ip;
328
									break;
329
								}
330
							}
331
						} else {
332
							foreach ($iflist as $ifent => $ifname) {
333
								$interface_ip = get_interface_ip($ifent);
334
								if (!is_ipaddrv4($interface_ip)) {
335
									continue;
336
								}
337
								if ($local_subnet == "0.0.0.0/0" || ip_in_subnet($interface_ip, $local_subnet)) {
338
									$srcip = $interface_ip;
339
									break;
340
								}
341
							}
342
						}
343
						/* if no valid src IP was found in configured interfaces, try the vips */
344
						if (is_null($srcip)) {
345
							$viplist = get_configured_vip_list();
346
							foreach ($viplist as $vip => $address) {
347
								if (ip_in_subnet($address, $local_subnet)) {
348
									$srcip = $address;
349
									break;
350
								}
351
							}
352
						}
353
						$dstip = $ph2ent['pinghost'];
354
						if (is_ipaddrv6($dstip)) {
355
							$family = "inet6";
356
						} else {
357
							$family = "inet";
358
						}
359
						if (is_ipaddr($srcip)) {
360
							$ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n";
361
							$ipsecpinghostsactive = true;
362
						}
363
					}
364
				}
365
			}
366
			if ($is_vti) {
367
				interface_ipsec_vti_configure($ph1ent);
368
			}
369
		}
370
		@file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts);
371
		unset($ipsecpinghosts);
372
	}
373
	unset($iflist);
374
	/* Build a list of all IPsec interfaces configured on the firewall at the OS level */
375
	foreach (get_interface_arr() as $thisif) {
376
		if (substr($thisif, 0, 5) == "ipsec") {
377
			$ipsec_vti_cleanup_ifs[] = $thisif;
378
		}
379
	}
380

    
381
	$accept_unencrypted = "";
382
	if (isset($config['ipsec']['acceptunencryptedmainmode'])) {
383
		$accept_unencrypted = "accept_unencrypted_mainmode_messages = yes";
384
	}
385

    
386
	$stronconf = '';
387
	if (file_exists("{$g['varetc_path']}/ipsec/strongswan.conf")) {
388
		$stronconf = file_get_contents("{$g['varetc_path']}/ipsec/strongswan.conf");
389
	}
390

    
391
	$i_dont_care_about_security_and_use_aggressive_mode_psk = "";
392
	if ($aggressive_mode_psk) {
393
		log_error("WARNING: Setting i_dont_care_about_security_and_use_aggressive_mode_psk option because a phase 1 is configured using aggressive mode with pre-shared keys. This is not a secure configuration.");
394
		if (!empty($stronconf) && strpos($stronconf, 'i_dont_care_about_security_and_use_aggressive_mode_psk') === FALSE) {
395
			$restart = true;
396
		}
397
		$i_dont_care_about_security_and_use_aggressive_mode_psk = "i_dont_care_about_security_and_use_aggressive_mode_psk=yes";
398
	}
399

    
400
	$unity_enabled = isset($config['ipsec']['unityplugin']) ? 'yes' : 'no';
401

    
402
	$makebeforebreak = '';
403
	if (isset($config['ipsec']['makebeforebreak'])) {
404
		$makebeforebreak = 'make_before_break = yes';
405
	}
406

    
407
	if (isset($config['ipsec']['enableinterfacesuse'])) {
408
		if (!empty($ifacesuse)) {
409
			$ifacesuse = 'interfaces_use = ' . implode(',', array_unique($ifacesuse));
410
		} else {
411
			$ifacesuse = '';
412
		}
413
	} else {
414
		$ifacesuse = '';
415
	}
416

    
417
	unset($stronconf);
418

    
419
	$strongswanlog = "";
420
	$ipsecloglevels = vpn_logging_cfgtxt();
421
	if (is_array($ipsecloglevels)) {
422
		foreach ($ipsecloglevels as $loglevel) {
423
			$strongswanlog .= "\t\t\t" . $loglevel . "\n";
424
		}
425
	}
426
	$strongswan = <<<EOD
427

    
428
# Automatically generated config file - DO NOT MODIFY. Changes will be overwritten.
429
starter {
430
	load_warning = no
431
	config_file = {$g['varetc_path']}/ipsec/ipsec.conf
432
}
433

    
434
charon {
435
# number of worker threads in charon
436
	threads = 16
437
	ikesa_table_size = 32
438
	ikesa_table_segments = 4
439
	init_limit_half_open = 1000
440
	install_routes = no
441
	load_modular = yes
442
	ignore_acquire_ts = yes
443
	{$i_dont_care_about_security_and_use_aggressive_mode_psk}
444
	{$accept_unencrypted}
445
	cisco_unity = {$unity_enabled}
446
	{$ifacesuse}
447
	{$makebeforebreak}
448

    
449
	syslog {
450
		identifier = charon
451
		# log everything under daemon since it ends up in the same place regardless with our syslog.conf
452
		daemon {
453
			ike_name = yes
454
{$strongswanlog}
455
		}
456
		# disable logging under auth so logs aren't duplicated
457
		auth {
458
			default = -1
459
		}
460
	}
461

    
462
	plugins {
463
		# Load defaults
464
		include {$g['varetc_path']}/ipsec/strongswan.d/charon/*.conf
465

    
466
		stroke {
467
			secrets_file = {$g['varetc_path']}/ipsec/ipsec.secrets
468
		}
469

    
470
		unity {
471
			load = {$unity_enabled}
472
		}
473

    
474
EOD;
475

    
476
	/* Find RADIUS servers designated for Mobile IPsec user auth */
477
	$radius_server_txt = "";
478
	$user_sources = explode(',', $config['ipsec']['client']['user_source']);
479
	foreach ($user_sources as $user_source) {
480
		$auth_server = auth_get_authserver($user_source);
481
		$nice_user_source = strtolower(preg_replace('/[\s\.]+/', '_', $user_source));
482
		if ($auth_server && $auth_server['type'] === 'radius') {
483
			$radius_server_txt .= <<<EOD
484
				{$nice_user_source} {
485
					address = {$auth_server['host']}
486
					secret = "{$auth_server['radius_secret']}"
487
					auth_port = {$auth_server['radius_auth_port']}
488
					acct_port = {$auth_server['radius_acct_port']}
489
				}
490

    
491
EOD;
492
		}
493
	}
494

    
495
	/* Activate RADIUS accounting if it was selected on the auth server view */
496
	$radius_accounting = "";
497
	if($auth_server && isset($auth_server['radius_acct_port'])){
498
		$radius_accounting = 'accounting = yes';
499
	}
500

    
501
	/* write an eap-radius config section if appropriate */
502
	if (strlen($radius_server_txt) && ($mobile_ipsec_auth === "eap-radius")) {
503
		$strongswan .= <<<EOD
504
		eap-radius {
505
			class_group = yes
506
			eap_start = no
507
			{$radius_accounting}
508
			servers {
509
{$radius_server_txt}
510
			}
511
		}
512

    
513
EOD;
514
	}
515

    
516
	if (is_array($a_client) && isset($a_client['enable'])) {
517
		$strongswan .= "\t\tattr {\n";
518
		
519
		$cfgservers = array();
520
		if (!empty($a_client['wins_server1'])) {
521
			$cfgservers[] = $a_client['wins_server1'];
522
		}
523
		if (!empty($a_client['wins_server2'])) {
524
			$cfgservers[] = $a_client['wins_server2'];
525
		}
526
		if (!empty($cfgservers)) {
527
			$strongswan .= "\t\t\tnbns = " . implode(",", $cfgservers) . "\n";
528
		}
529
		unset($cfgservers);
530

    
531
		if (isset($a_client['net_list']) && is_array($a_phase2)) {
532
			$net_list = '';
533
			foreach ($a_phase2 as $ph2ent) {
534
				if (isset($ph2ent['disabled'])) {
535
					continue;
536
				}
537

    
538
				if (!isset($ph2ent['mobile'])) {
539
					continue;
540
				}
541

    
542
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
543

    
544
				if (!empty($net_list)) {
545
					$net_list .= ",";
546
				}
547
				$net_list .= $localid;
548
			}
549

    
550
			if (!empty($net_list)) {
551
				$strongswan .= "\t\t\tsubnet = {$net_list}\n";
552
				$strongswan .= "\t\t\tsplit-include = {$net_list}\n";
553
				unset($net_list);
554
			}
555
		}
556

    
557
		if (!empty($a_client['dns_domain'])) {
558
			$strongswan .= "\t\t\t# Search domain and default domain\n";
559
			$strongswan .= "\t\t\t28674 = \"{$a_client['dns_domain']}\"\n";
560
			if (empty($a_client['dns_split'])) {
561
				$strongswan .= "\t\t\t28675 = \"{$a_client['dns_domain']}\"";
562
			}
563
			$strongswan .= "\n";
564
		}
565

    
566
		if (!empty($a_client['dns_split'])) {
567
			$strongswan .= "\t\t\t28675 = {$a_client['dns_split']}\n";
568
		}
569

    
570
		if (!empty($a_client['login_banner'])) {
571
			$strongswan .= "\t\t\t28672 = \"{$a_client['login_banner']}\"\n";
572
		}
573

    
574
		if (isset($a_client['save_passwd'])) {
575
			$strongswan .= "\t\t\t28673 = 1\n";
576
		}
577

    
578
		if ($a_client['pfs_group']) {
579
			$strongswan .= "\t\t\t28679 = \"{$a_client['pfs_group']}\"\n";
580
		}
581
		$strongswan .= "\t\t}\n";
582

    
583
		if ($a_client['user_source'] != "none") {
584
			$strongswan .= "\t\txauth-generic {\n";
585
			$strongswan .= "\t\t\tscript = /etc/inc/ipsec.auth-user.php\n";
586
			$strongswan .= "\t\t\tauthcfg = ";
587
			$firstsed = 0;
588
			$authcfgs = explode(",", $a_client['user_source']);
589
			foreach ($authcfgs as $authcfg) {
590
				if ($firstsed > 0) {
591
					$strongswan .= ",";
592
				}
593
				if ($authcfg == "system") {
594
					$authcfg = "Local Database";
595
				}
596
				$strongswan .= $authcfg;
597
				$firstsed = 1;
598
			}
599
			$strongswan .= "\n";
600
			$strongswan .= "\t\t}\n";
601
		}
602
	}
603

    
604
	$strongswan .= "\n\t}\n}\n";
605
	@file_put_contents("{$g['varetc_path']}/ipsec/strongswan.conf", $strongswan);
606
	unset($strongswan);
607

    
608
	/* write out CRL files */
609
	if (is_array($config['crl']) && count($config['crl'])) {
610
		foreach ($config['crl'] as $crl) {
611
			if (!isset($crl['text'])) {
612
				log_error(sprintf(gettext("Warning: Missing CRL data for %s"), $crl['descr']));
613
				continue;
614
			}
615
			$fpath = "{$crlpath}/{$crl['refid']}.crl";
616
			if (!@file_put_contents($fpath, base64_decode($crl['text']))) {
617
				log_error(sprintf(gettext("Error: Cannot write IPsec CRL file for %s"), $crl['descr']));
618
				continue;
619
			}
620
		}
621
	}
622

    
623
	$pskconf = "";
624

    
625
	$vpncas = array();
626
	if (is_array($a_phase1) && count($a_phase1)) {
627
		foreach ($a_phase1 as $ph1ent) {
628

    
629
			if (isset($ph1ent['disabled'])) {
630
				continue;
631
			}
632

    
633
			if (strstr($ph1ent['authentication_method'], 'rsa') ||
634
			    in_array($ph1ent['authentication_method'], array('eap-mschapv2', 'eap-tls', 'eap-radius'))) {
635
				$certline = '';
636

    
637
				$ikeid = $ph1ent['ikeid'];
638
				$cert = lookup_cert($ph1ent['certref']);
639

    
640
				if (!$cert) {
641
					log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
642
					continue;
643
				}
644

    
645
				/* add signing CA cert chain of server cert
646
				 * to the list of CAs to write
647
				 */
648
				$cachain = ca_chain_array($cert);
649
				if ($cachain && is_array($cachain)) {
650
					foreach ($cachain as $cacrt) {
651
						$vpncas[$cacrt['refid']] = $cacrt;
652
					}
653
				}
654

    
655
				@chmod($certpath, 0600);
656

    
657
				$ph1keyfile = "{$keypath}/cert-{$ikeid}.key";
658
				if (!file_put_contents($ph1keyfile, base64_decode($cert['prv']))) {
659
					log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
660
					continue;
661
				}
662
				@chmod($ph1keyfile, 0600);
663

    
664
				$ph1certfile = "{$certpath}/cert-{$ikeid}.crt";
665
				if (!file_put_contents($ph1certfile, base64_decode($cert['crt']))) {
666
					log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
667
					@unlink($ph1keyfile);
668
					continue;
669
				}
670
				@chmod($ph1certfile, 0600);
671

    
672
				/* XXX" Traffic selectors? */
673
				$pskconf .= " : RSA {$ph1keyfile}\n";
674
			} else {
675
				list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local');
676
				list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap);
677

    
678
				$myid = trim($myid_data);
679

    
680
				if (empty($peerid_data)) {
681
					continue;
682
				}
683

    
684
				if ($myid_type == 'fqdn' && !empty($myid)) {
685
					$myid = "@{$myid}";
686
				}
687

    
688
				$myid = isset($ph1ent['mobile']) ? trim($myid_data) : "%any";
689

    
690
				$peerid = ($peerid_data != 'allusers') ? trim($peerid_data) : '';
691

    
692
				if ($peerid_type == 'fqdn' && !empty($peerid)) {
693
					$peerid = "@{$peerid}";
694
				}
695

    
696
				if (!empty($ph1ent['pre-shared-key'])) {
697
					$pskconf .= "{$myid} {$peerid} : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n";
698
					if (isset($ph1ent['mobile'])) {
699
						$pskconf .= "{$myid} %any : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n";
700
						$pskconf .= " : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n";
701
					}
702
				}
703
			}
704

    
705
			/* if the client authenticates with a cert add the
706
			 * client cert CA chain to the list of CAs to write
707
			 */
708
			if (in_array($ph1ent['authentication_method'],
709
			array('rsasig', 'eap-tls', 'xauth_rsa_server'))) {
710

    
711
				if (!empty($ph1ent['caref']) && !array_key_exists($ph1ent['caref'], $vpncas)) {
712
					$thisca = lookup_ca($ph1ent['caref']);
713
					$vpncas[$ph1ent['caref']] = $thisca;
714

    
715
					/* follow chain up to root */
716
					$cachain = ca_chain_array($thisca);
717
					if ($cachain and is_array($cachain)) {
718
						foreach ($cachain as $cacrt) {
719
							$vpncas[$cacrt['refid']] = $cacrt;
720
						}
721
					}
722
				}
723
			}
724
		}
725
	}
726

    
727
	/* write the required CAs */
728
	foreach ($vpncas as $carefid => $cadata) {
729
		$cacrt = base64_decode($cadata['crt']);
730
		$cacrtattrs = openssl_x509_parse($cacrt);
731
		if (!is_array($cacrtattrs) || !isset($cacrtattrs['hash'])) {
732
			log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $cadata['descr']));
733
			continue;
734
		}
735
		$cafilename = "{$capath}/{$cacrtattrs['hash']}.0.crt";
736
		if (!@file_put_contents($cafilename, $cacrt)) {
737
				log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $cadata['descr']));
738
				continue;
739
		}
740
	}
741

    
742
	/* Add user PSKs */
743
	if (is_array($config['system']) && is_array($config['system']['user'])) {
744
		foreach ($config['system']['user'] as $user) {
745
			if (!empty($user['ipsecpsk'])) {
746
				$pskconf .= "{$myid} {$user['name']} : PSK 0s" . base64_encode($user['ipsecpsk']) . "\n";
747
			}
748
		}
749
		unset($user);
750
	}
751

    
752
	/* add PSKs for mobile clients */
753
	if (is_array($ipseccfg['mobilekey'])) {
754
		foreach ($ipseccfg['mobilekey'] as $key) {
755
			if ($key['ident'] == "allusers") {
756
				$key['ident'] = '%any';
757
			}
758
			if ($key['ident'] == "any") {
759
				$key['ident'] = '%any';
760
			}
761
			if (empty($key['type'])) {
762
				$key['type'] = 'PSK';
763
			}
764
			$pskconf .= " {$key['ident']} : {$key['type']} 0s" . base64_encode($key['pre-shared-key']) . "\n";
765
		}
766
		unset($key);
767
	}
768

    
769
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.secrets", $pskconf);
770
	chmod("{$g['varetc_path']}/ipsec/ipsec.secrets", 0600);
771
	unset($pskconf);
772

    
773
	$uniqueids = 'yes';
774
	if (!empty($config['ipsec']['uniqueids'])) {
775
		if (array_key_exists($config['ipsec']['uniqueids'], $ipsec_idhandling)) {
776
			$uniqueids = $config['ipsec']['uniqueids'];
777
		}
778
	}
779
	$natfilterrules = false;
780
	/* begin ipsec.conf */
781
	$ipsecconf = "";
782
	$enablecompression = false;
783
	if (is_array($a_phase1) && count($a_phase1)) {
784

    
785
		$ipsecconf .= "# This file is automatically generated. Do not edit\n";
786
		$ipsecconf .= "config setup\n\tuniqueids = {$uniqueids}\n";
787

    
788
		if (isset($config['ipsec']['strictcrlpolicy'])) {
789
			$ipsecconf .= "\tstrictcrlpolicy = yes \n";
790
		}
791

    
792
		if (!isset($config['ipsec']['noshuntlaninterfaces'])) {
793
			$bypassnets = array();
794
			if ($config['interfaces']['lan']) {
795
				$lanip = get_interface_ip("lan");
796
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
797
					$lansn = get_interface_subnet("lan");
798
					$lansa = gen_subnetv4($lanip, $lansn);
799
					if (!empty($lansa) && !empty($lansn)) {
800
						$bypassnets[] = "{$lansa}/{$lansn}";
801
					}
802
				}
803
				$lanip6 = get_interface_ipv6("lan");
804
				if (!empty($lanip6) && is_ipaddrv6($lanip6)) {
805
					$lansn6 = get_interface_subnetv6("lan");
806
					$lansa6 = gen_subnetv6($lanip6, $lansn6);
807
					if (!empty($lansa6) && !empty($lansn6)) {
808
						$bypassnets[] = "{$lansa6}/{$lansn6}";
809
					}
810
				}
811
			}
812
			if (!empty($bypassnets)) {
813
				$bypass = implode(',', $bypassnets);
814
				$ipsecconf .= <<<EOD
815

    
816
conn bypasslan
817
	leftsubnet = {$bypass}
818
	rightsubnet = {$bypass}
819
	authby = never
820
	type = passthrough
821
	auto = route
822

    
823
EOD;
824
			}
825
		}
826

    
827
		foreach ($a_phase1 as $ph1ent) {
828
			if (isset($ph1ent['disabled'])) {
829
				continue;
830
			}
831

    
832
			if ($ph1ent['mode'] == "aggressive") {
833
				$aggressive = "yes";
834
			} else {
835
				$aggressive = "no";
836
			}
837

    
838
			$ep = ipsec_get_phase1_src($ph1ent);
839
			if (!$ep) {
840
				continue;
841
			}
842

    
843
			$ikeid = $ph1ent['ikeid'];
844
			$keyexchange = "ikev1";
845
			$passive = "route";
846
			if (!empty($ph1ent['iketype'])) {
847
				if ($ph1ent['iketype'] == "ikev2") {
848
					$keyexchange = "ikev2";
849
				} elseif ($ph1ent['iketype'] == "auto") {
850
					$keyexchange = "ike";
851
				}
852
			}
853

    
854
			if (isset($ph1ent['mobile'])) {
855
				$right_spec = "%any";
856
				$passive = 'add';
857
			} else {
858
				if (isset($ph1ent['responderonly'])) {
859
					$passive = 'add';
860
				}
861

    
862
				$right_spec = $ph1ent['remote-gateway'];
863
				if (is_ipaddr($right_spec)) {
864
					$sourcehost = $right_spec;
865
				} else {
866
					$sourcehost = $rgmap[$right_spec];
867
				}
868

    
869
				if (substr($ph1ent['interface'], 0, 4) == "_vip") {
870
					$vpninterface = get_configured_vip_interface($ph1ent['interface']);
871
					if (substr($vpninterface, 0, 4) == "_vip") {
872
						// vips are nested if its a ipalias with a carp parent
873
						$vpninterface = get_configured_vip_interface($vpninterface);
874
					}
875
					$ifacesuse = get_real_interface($vpninterface);
876
				} else {
877
					$ifacesuse = get_failover_interface($ph1ent['interface']);
878
					if (substr($ifacesuse, 0, 4) == "_vip") {
879
						$vpninterface = get_configured_vip_interface($ifacesuse);
880
						$ifacesuse = get_real_interface($vpninterface);
881
					} else {
882
						$vpninterface = convert_real_interface_to_friendly_interface_name($ifacesuse);
883
					}
884
				}
885
				if ($ph1ent['protocol'] == 'inet') {
886
					if (!empty($ifacesuse) && interface_has_gateway($vpninterface)) {
887
						$gatewayip = get_interface_gateway($vpninterface);
888
						$interfaceip = get_interface_ip($vpninterface);
889
						$subnet_bits = get_interface_subnet($vpninterface);
890
						$subnet_ip = gen_subnetv4($interfaceip, $subnet_bits);
891
						/* if the remote gateway is in the local subnet, then don't add a route */
892
						if (is_ipaddrv4($sourcehost) &&
893
						    !ip_in_subnet($sourcehost, "{$subnet_ip}/{$subnet_bits}")) {
894
							if (is_ipaddrv4($gatewayip)) {
895
								// log_error("IPSEC interface is not WAN but {$ifacesuse}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
896
								route_add_or_change("-host {$sourcehost} {$gatewayip}");
897
							}
898
						}
899
					}
900
				} else if ($ph1ent['protocol'] == 'inet6') {
901
					if (!empty($ifacesuse) && interface_has_gatewayv6($vpninterface)) {
902
						$gatewayip = get_interface_gateway_v6($vpninterface);
903
						$interfaceip = get_interface_ipv6($vpninterface);
904
						$subnet_bits = get_interface_subnetv6($vpninterface);
905
						$subnet_ip = gen_subnetv6($interfaceip, $subnet_bits);
906
						/* if the remote gateway is in the local subnet, then don't add a route */
907
						if (is_ipaddrv6($sourcehost) &&
908
						    !ip_in_subnet($sourcehost, "{$subnet_ip}/{$subnet_bits}")) {
909
							if (is_ipaddrv6($gatewayip)) {
910
								// log_error("IPSEC interface is not WAN but {$ifacesuse}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
911
								route_add_or_change("-inet6 -host {$sourcehost} {$gatewayip}");
912
							}
913
						}
914
					}
915
				}
916
			}
917

    
918
			list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local');
919
			if ($myid_type != 'address' && $myid_type != 'keyid' && $myid_type != 'asn1dn') {
920
				$myid_data = "{$myid_type}:{$myid_data}";
921
			} elseif ($myid_type == "asn1dn" && !empty($myid_data)) {
922
				if ($myid_data[0] == '#') {
923
				/* asn1dn needs double quotes */
924
					$myid_data = "\"{$myid_type}:{$myid_data}\"";
925
				} else {
926
					$myid_data = "\"{$myid_data}\"";
927
				}
928
			}
929
			$leftid = '';
930
			if (!empty($myid_data)) {
931
				$leftid = "leftid = {$myid_data}";
932
			}
933

    
934
			$peerid_spec = '';
935
			if (isset($ph1ent['mobile']) && ($ph1ent['authentication_method'] == "pre_shared_key" || $ph1ent['authentication_method'] == "xauth_psk_server")) {
936
				// Only specify peer ID if we are not dealing with mobile PSK
937
			} else {
938
				list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap);
939
				if ($peerid_type == 'any') {
940
					$peerid_spec = '';
941
				} elseif ($peerid_type != 'address' && $peerid_type != 'keyid' && $peerid_type != 'asn1dn') {
942
					$peerid_spec = "{$peerid_type}:{$peerid_data}";
943
				} elseif ($peerid_type == "asn1dn") {
944
					/* asn1dn needs double quotes */
945
					if ($peerid_data[0] == '#') {
946
						$peerid_spec = "\"{$peerid_type}:{$peerid_data}\"";
947
					} elseif (!empty($peerid_data)) {
948
						$peerid_spec = "\"{$peerid_data}\"";
949
					}
950
				} else {
951
					$peerid_spec = $peerid_data;
952
				}
953
			}
954

    
955
			$ealgosp1 = '';
956
			if (is_array($ph1ent['encryption']['item'])) {
957
				$ciphers = "";
958
				foreach($ph1ent['encryption']['item'] as $p1enc) {
959
					if (!is_array($p1enc['encryption-algorithm']) ||
960
							empty($p1enc['encryption-algorithm']['name']) ||
961
							empty($p1enc['hash-algorithm'])) {
962
						continue;
963
					}
964
					$ciphers .= ",";
965
					$ciphers .= $p1enc['encryption-algorithm']['name'];
966
					$ealg_kl = $p1enc['encryption-algorithm']['keylen'];
967
					if ($ealg_kl) {
968
						$ciphers .= "{$ealg_kl}";
969
					}
970
					$ciphers .= "-{$p1enc['hash-algorithm']}";
971

    
972
					$modp = vpn_ipsec_convert_to_modp($p1enc['dhgroup']);
973
					if (!empty($modp)) {
974
						$ciphers .= "-{$modp}";
975
					}
976
				}
977
				$ciphers = substr($ciphers, 1);
978
				$ealgosp1 = "ike = {$ciphers}!";
979
			}
980

    
981
			if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
982
				if ($passive == "route") {
983
					$dpdline = "dpdaction = restart";
984
				} else {
985
					$dpdline = "dpdaction = clear";
986
				}
987
				$dpdline .= "\n\tdpddelay = {$ph1ent['dpd_delay']}s";
988
				$dpdtimeout = $ph1ent['dpd_delay'] * ($ph1ent['dpd_maxfail'] + 1);
989
				$dpdline .= "\n\tdpdtimeout = {$dpdtimeout}s";
990
			} else {
991
				$dpdline = "dpdaction = none";
992
			}
993

    
994
			$ikelifeline = '';
995
			if ($ph1ent['lifetime']) {
996
				$ikelifeline = "ikelifetime = {$ph1ent['lifetime']}s";
997
			}
998

    
999
			$rightsourceip = NULL;
1000
			$rightdnsserver = NULL;
1001
			if (isset($ph1ent['mobile'])) {
1002
				$rightsourceips = array();
1003
				if (!empty($a_client['pool_address'])) {
1004
					$rightsourceips[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
1005
				}
1006
				if (!empty($a_client['pool_address_v6'])) {
1007
					$rightsourceips[] = "{$a_client['pool_address_v6']}/{$a_client['pool_netbits_v6']}";
1008
				}
1009
				if ($ph1ent['authentication_method'] == "eap-radius" && !count($rightsourceips)) {
1010
					$rightsourceips[] = "%radius";
1011
				}
1012
				if (count($rightsourceips)) {
1013
					$rightsourceip = "\trightsourceip = " . implode(',', $rightsourceips) . "\n";
1014
				}
1015

    
1016
				$rightdnsservers = array();
1017
				if (!empty($a_client['dns_server1'])) {
1018
					$rightdnsservers[] = $a_client['dns_server1'];
1019
				}
1020
				if (!empty($a_client['dns_server2'])) {
1021
					$rightdnsservers[] = $a_client['dns_server2'];
1022
				}
1023
				if (!empty($a_client['dns_server3'])) {
1024
					$rightdnsservers[] = $a_client['dns_server3'];
1025
				}
1026
				if (!empty($a_client['dns_server4'])) {
1027
					$rightdnsservers[] = $a_client['dns_server4'];
1028
				}
1029
				
1030
				if (count($rightdnsservers)) {
1031
					$rightdnsserver = "\trightdns = " . implode(',', $rightdnsservers) . "\n";
1032
				}
1033
			}
1034

    
1035
			if (!empty($ph1ent['caref'])) {
1036
				$ca = lookup_ca($ph1ent['caref']);
1037
				if ($ca) {
1038
					$casubarr = cert_get_subject_array($ca['crt']);
1039
					$casub = "";
1040
					foreach ($casubarr as $casubfield) {
1041
						if (empty($casub)) {
1042
							$casub = "/";
1043
						}
1044
						/* The subfield value could be an array. To avoid duplicating code,
1045
						 * always make it an array then iterate.
1046
						 * See https://redmine.pfsense.org/issues/7929
1047
						 */
1048
						if (!is_array($casubfield['v'])) {
1049
							$casubfield['v'] = array($casubfield['v']);
1050
						}
1051
						foreach ($casubfield['v'] as $casubval) {
1052
							$casub .= "{$casubfield['a']}={$casubval}/";
1053
						}
1054
					}
1055

    
1056
				}
1057
			}
1058

    
1059
			$authentication = "";
1060
			switch ($ph1ent['authentication_method']) {
1061
				case 'eap-mschapv2':
1062
					if (isset($ph1ent['mobile'])) {
1063
						$authentication = "eap_identity=%any\n\t";
1064
						$authentication .= "leftauth=pubkey\n\trightauth=eap-mschapv2";
1065
						if (!empty($ph1ent['certref'])) {
1066
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1067
							$authentication .= "\n\tleftsendcert=always";
1068
						}
1069
					}
1070
					break;
1071
				case 'eap-tls':
1072
					if (isset($ph1ent['mobile'])) {
1073
						$authentication = "eap_identity=%identity\n\t";
1074
						$authentication .= "leftauth=pubkey\n\trightauth=eap-tls";
1075
						if (!empty($ph1ent['certref'])) {
1076
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1077
							$authentication .= "\n\tleftsendcert=always";
1078
						}
1079
					} else {
1080
						$authentication = "leftauth=eap-tls\n\trightauth=eap-tls";
1081
						if (!empty($ph1ent['certref'])) {
1082
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1083
							$authentication .= "\n\tleftsendcert=always";
1084
						}
1085
					}
1086
					if (isset($casub)) {
1087
						$authentication .= "\n\trightca=\"$casub\"";
1088
					}
1089
					break;
1090
				case 'eap-radius':
1091
					if (isset($ph1ent['mobile'])) {
1092
						$authentication = "eap_identity=%identity\n\t";
1093
						$authentication .= "leftauth=pubkey\n\trightauth=eap-radius";
1094
						if (!empty($ph1ent['certref'])) {
1095
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1096
							$authentication .= "\n\tleftsendcert=always";
1097
						}
1098
					} else {
1099
						$authentication = "leftauth=eap-radius\n\trightauth=eap-radius";
1100
						if (!empty($ph1ent['certref'])) {
1101
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1102
							$authentication .= "\n\tleftsendcert=always";
1103
						}
1104
					}
1105
					break;
1106
				case 'xauth_rsa_server':
1107
					$authentication = "leftauth = pubkey\n\trightauth = pubkey";
1108
					$authentication .= "\n\trightauth2 = xauth-generic";
1109
					if (!empty($ph1ent['certref'])) {
1110
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1111
						$authentication .= "\n\tleftsendcert=always";
1112
					}
1113
					if (isset($casub)) {
1114
						$authentication .= "\n\trightca=\"$casub\"";
1115
					}
1116
					break;
1117
				case 'xauth_psk_server':
1118
					$authentication = "leftauth = psk\n\trightauth = psk";
1119
					$authentication .= "\n\trightauth2 = xauth-generic";
1120
					break;
1121
				case 'pre_shared_key':
1122
					$authentication = "leftauth = psk\n\trightauth = psk";
1123
					break;
1124
				case 'rsasig':
1125
					$authentication = "leftauth = pubkey\n\trightauth = pubkey";
1126
					if (!empty($ph1ent['certref'])) {
1127
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1128
						$authentication .= "\n\tleftsendcert=always";
1129
					}
1130
					if (isset($casub)) {
1131
						$authentication .= "\n\trightca=\"$casub\"";
1132
					}
1133
					break;
1134
				case 'hybrid_rsa_server':
1135
					$authentication = "leftauth = pubkey\n\trightauth = xauth-generic";
1136
					if (!empty($ph1ent['certref'])) {
1137
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1138
						$authentication .= "\n\tleftsendcert=always";
1139
					}
1140
					break;
1141
			}
1142

    
1143
			$left_spec = $ep;
1144

    
1145
			if (isset($ph1ent['reauth_enable'])) {
1146
				$reauth = "reauth = no";
1147
			} else {
1148
				$reauth = "reauth = yes";
1149
			}
1150

    
1151
			if (isset($ph1ent['rekey_enable'])) {
1152
				$rekeyline = "rekey = no";
1153
			} else {
1154
				$rekeyline = "rekey = yes";
1155
				if(!empty($ph1ent['margintime'])){
1156
					$rekeyline .= "\n\tmargintime = {$ph1ent['margintime']}s";
1157
				}
1158
			}
1159

    
1160
			if ($ph1ent['nat_traversal'] == 'off') {
1161
				$forceencaps = 'forceencaps = no';
1162
			} else if ($ph1ent['nat_traversal'] == 'force') {
1163
				$forceencaps = 'forceencaps = yes';
1164
			} else {
1165
				$forceencaps = 'forceencaps = no';
1166
			}
1167

    
1168
			if ($ph1ent['mobike'] == 'on') {
1169
				$mobike = 'mobike = yes';
1170
			} else {
1171
				$mobike = 'mobike = no';
1172
			}
1173

    
1174
			if (isset($ph1ent['tfc_enable'])) {
1175
				if (isset($ph1ent['tfc_bytes']) && is_numericint($ph1ent['tfc_bytes'])) {
1176
					$tfc = "tfc = {$ph1ent['tfc_bytes']}";
1177
				} else {
1178
					$tfc = "tfc = %mtu";
1179
				}
1180
			}
1181

    
1182
			$ipseclifetime = 0;
1183
			$rightsubnet_spec = array();
1184
			$leftsubnet_spec = array();
1185
			$reqids = array();
1186
			$vtireq = array();
1187
			$ealgoAHsp2arr = array();
1188
			$ealgoESPsp2arr = array();
1189
			if (is_array($a_phase2) && count($a_phase2)) {
1190
				foreach ($a_phase2 as $ph2ent) {
1191
					if ($ikeid != $ph2ent['ikeid']) {
1192
						continue;
1193
					}
1194

    
1195
					if (isset($ph2ent['disabled'])) {
1196
						continue;
1197
					}
1198

    
1199
					if (isset($ph2ent['mobile']) && !isset($a_client['enable'])) {
1200
						continue;
1201
					}
1202

    
1203
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
1204
						$tunneltype = "type = tunnel";
1205
						$installpolicy = "installpolicy = yes";
1206

    
1207
						$localid_type = $ph2ent['localid']['type'];
1208
						$leftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']);
1209

    
1210
						/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
1211
						if (($localid_type == "none" || $localid_type == "mobile") &&
1212
						    isset($ph1ent['mobile']) && (ipsec_get_number_of_phase2($ikeid) == 1)) {
1213
							$left_spec = '%any';
1214
						} else {
1215
							if ($localid_type != "address") {
1216
								$localid_type = "subnet";
1217
							}
1218
							// Don't let an empty subnet into config, it can cause parse errors. Ticket #2201.
1219
							if (!is_ipaddr($leftsubnet_data) && !is_subnet($leftsubnet_data) && ($leftsubnet_data != "0.0.0.0/0")) {
1220
								log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet.");
1221
								continue;
1222
							}
1223
							if (!empty($ph2ent['natlocalid'])) {
1224
								$natleftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], false, $ph2ent['mode']);
1225
								if ($ph2ent['natlocalid']['type'] != "address") {
1226
									if (is_subnet($natleftsubnet_data)) {
1227
										$leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}";
1228
									}
1229
								} else {
1230
									if (is_ipaddr($natleftsubnet_data)) {
1231
										$leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}";
1232
									}
1233
								}
1234
								$natfilterrules = true;
1235
							}
1236
						}
1237

    
1238
						$leftsubnet_spec[] = $leftsubnet_data;
1239

    
1240
						if (!isset($ph2ent['mobile'])) {
1241
							$tmpsubnet = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
1242
							$rightsubnet_spec[] = $tmpsubnet;
1243
						} else if (!empty($a_client['pool_address'])) {
1244
							$rightsubnet_spec[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
1245
						}
1246
					} elseif ($ph2ent['mode'] == 'vti') {
1247
						$tunneltype = "";
1248
						$installpolicy = "installpolicy = no";
1249
						$passive = 'start';
1250

    
1251
						$localid_type = $ph2ent['localid']['type'];
1252
						$leftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']);
1253
						$leftsubnet_spec[] = $leftsubnet_data;
1254

    
1255
						$tmpsubnet = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
1256
						$rightsubnet_spec[] = $tmpsubnet;
1257
						$vtireq[] = $ph2ent['reqid'];
1258
					} else {
1259
						$tunneltype = "type = transport";
1260
						$installpolicy = "installpolicy = yes";
1261

    
1262
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
1263
						    ($ph1ent['authentication_method'] == "pre_shared_key")) &&
1264
						    isset($ph1ent['mobile'])) {
1265
							$left_spec = "%any";
1266
						} else {
1267
							$tmpsubnet = ipsec_get_phase1_src($ph1ent);
1268
							$leftsubnet_spec[] = $tmpsubnet;
1269
						}
1270

    
1271
						if (!isset($ph2ent['mobile'])) {
1272
							$rightsubnet_spec[] = $right_spec;
1273
						}
1274
					}
1275

    
1276
					if (isset($a_client['pfs_group']) && isset($ph2ent['mobile'])) {
1277
						$ph2ent['pfsgroup'] = $a_client['pfs_group'];
1278
					}
1279

    
1280
					if ($ph2ent['protocol'] == 'esp') {
1281
						if (is_array($ph2ent['encryption-algorithm-option'])) {
1282
							foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
1283
								$ealg_id = $ealg['name'];
1284
								$ealg_kl = $ealg['keylen'];
1285

    
1286
								if (!empty($ealg_kl) && $ealg_kl == "auto") {
1287
									if (empty($p2_ealgos) || !is_array($p2_ealgos)) {
1288
										require_once("ipsec.inc");
1289
									}
1290
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
1291
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
1292
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
1293
									/* XXX: in some cases where include ordering is suspect these variables
1294
									 * are somehow 0 and we enter this loop forever and timeout after 900
1295
									 * seconds wrecking bootup */
1296
									if ($key_hi != 0 and $key_lo != 0 and $key_step != 0) {
1297
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
1298
											if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1299
												foreach ($ph2ent['hash-algorithm-option'] as $halgo) {
1300
													$halgo = str_replace('hmac_', '', $halgo);
1301
													$tmpealgo = "{$ealg_id}{$keylen}-{$halgo}";
1302
													$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1303
													if (!empty($modp)) {
1304
														$tmpealgo .= "-{$modp}";
1305
													}
1306
													$ealgoESPsp2arr[] = $tmpealgo;
1307
												}
1308
											} else {
1309
												$tmpealgo = "{$ealg_id}{$keylen}";
1310
												$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1311
												if (!empty($modp)) {
1312
													$tmpealgo .= "-{$modp}";
1313
												}
1314
												$ealgoESPsp2arr[] = $tmpealgo;
1315
											}
1316
										}
1317
									}
1318
								} else {
1319
									if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1320
										foreach ($ph2ent['hash-algorithm-option'] as $halgo) {
1321
											$halgo = str_replace('hmac_', '', $halgo);
1322
											$tmpealgo = "{$ealg_id}{$ealg_kl}-{$halgo}";
1323
											$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1324
											if (!empty($modp)) {
1325
												$tmpealgo .= "-{$modp}";
1326
											}
1327
											$ealgoESPsp2arr[] = $tmpealgo;
1328
										}
1329
									} else {
1330
										$tmpealgo = "{$ealg_id}{$ealg_kl}";
1331
										$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1332
										if (!empty($modp)) {
1333
											$tmpealgo .= "-{$modp}";
1334
										}
1335
										$ealgoESPsp2arr[] = $tmpealgo;
1336
									}
1337
								}
1338
							}
1339
						}
1340
					} else if ($ph2ent['protocol'] == 'ah') {
1341
						if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1342
							$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1343
							foreach ($ph2ent['hash-algorithm-option'] as $tmpAHalgo) {
1344
								$tmpAHalgo = str_replace('hmac_', '', $tmpAHalgo);
1345
								if (!empty($modp)) {
1346
									$tmpAHalgo = "-{$modp}";
1347
								}
1348
								$ealgoAHsp2arr[] = $tmpAHalgo;
1349
							}
1350
						}
1351
					}
1352

    
1353
					$reqids[] = $ph2ent['reqid'];
1354
					if ($ph2ent['mode'] != 'vti') {
1355
						$vtireq[] = null;
1356
					}
1357

    
1358
					if (!empty($ph2ent['lifetime'])) {
1359
						if ($ipseclifetime == 0 || intval($ipseclifetime) > intval($ph2ent['lifetime'])) {
1360
							$ipseclifetime = intval($ph2ent['lifetime']);
1361
						}
1362
					}
1363

    
1364
				}
1365
			}
1366

    
1367
			$ipsecconnect =<<<EOD
1368
	fragmentation = yes
1369
	keyexchange = {$keyexchange}
1370
	{$reauth}
1371
	{$forceencaps}
1372
	{$mobike}
1373
	{$tfc}
1374
	{$rekeyline}
1375
	{$installpolicy}
1376
	{$tunneltype}
1377
	{$dpdline}
1378
	auto = {$passive}
1379
	left = {$left_spec}
1380
	right = {$right_spec}
1381
	{$leftid}
1382

    
1383
EOD;
1384

    
1385
			/* Disable ipcomp for now. redmine #6167
1386
			if (isset($config['ipsec']['compression'])) {
1387
				$ipsecconnect .= "\tcompress = yes\n";
1388
				$enablecompression = true;
1389
			} */
1390
			if (!empty($ikelifeline)) {
1391
				$ipsecconnect .= "\t{$ikelifeline}\n";
1392
			}
1393
			if ($ipseclifetime > 0) {
1394
				$ipsecconnect .= "\tlifetime = {$ipseclifetime}s\n";
1395
			}
1396
			if (!empty($rightsourceip)) {
1397
				$ipsecconnect .= "{$rightsourceip}";
1398
			}
1399
			if (!empty($rightdnsserver)) {
1400
				$ipsecconnect .= "{$rightdnsserver}";
1401
			}
1402
			if (!empty($ealgosp1)) {
1403
				$ipsecconnect .= "\t{$ealgosp1}\n";
1404
			}
1405
			if (!empty($ealgoAHsp2arr)) {
1406
				$ipsecconnect .= "\tah = " . join(',', $ealgoAHsp2arr) . "!\n";
1407
			}
1408
			if (!empty($ealgoESPsp2arr)) {
1409
				$ipsecconnect .= "\tesp = " . join(',', $ealgoESPsp2arr) . "!\n";
1410
			}
1411
			if (!empty($authentication)) {
1412
				$ipsecconnect .= "\t{$authentication}\n";
1413
			}
1414
			if (!empty($peerid_spec)) {
1415
				$ipsecconnect .= "\trightid = {$peerid_spec}\n";
1416
			}
1417
			if ($keyexchange != 'ikev2') {
1418
				$ipsecconnect .= "\taggressive = {$aggressive}\n";
1419
			}
1420

    
1421
			if (!isset($ph1ent['mobile']) && ($keyexchange == 'ikev1' || isset($ph1ent['splitconn']))) {
1422
				if (!empty($rightsubnet_spec)) {
1423
					$ipsecfin = '';
1424
					foreach ($rightsubnet_spec as $idx => $rsubnet) {
1425
						$ipsecfin .= "\nconn con{$ph1ent['ikeid']}00{$idx}\n";
1426
						//if (!empty($reqids[$idx])) {
1427
						//	$ipsecfin .= "\treqid = " . $reqids[$idx] . "\n";
1428
						//}
1429
						$rightadd = "";
1430
						$leftadd = "";
1431
						if (!empty($vtireq[$idx])) {
1432
							$ipsecfin .= "\treqid = {$ph1ent['ikeid']}00{$idx}\n";
1433
							/* This interface will be a valid IPsec interface, so remove it from the cleanup list. */
1434
							$ipsec_vti_cleanup_ifs = array_diff($ipsec_vti_cleanup_ifs, array("ipsec{$ph1ent['ikeid']}00{$idx}"));
1435
							$rightadd = ",0.0.0.0/0";
1436
							$leftadd = ",0.0.0.0/0";
1437
						}
1438
						$ipsecfin .= $ipsecconnect;
1439
						$ipsecfin .= "\trightsubnet = {$rsubnet}{$rightadd}\n";
1440
						$ipsecfin .= "\tleftsubnet = " . $leftsubnet_spec[$idx] . "{$leftadd}\n";
1441
					}
1442
				} else {
1443
					log_error(sprintf(gettext("No phase2 specifications for tunnel with REQID = %s"), $ikeid));
1444
				}
1445
			} else {
1446
				if (isset($ph1ent['mobile'])) {
1447
					$ipsecfin = "\nconn con-mobile\n";
1448
				}
1449
				else {
1450
					$ipsecfin = "\nconn con{$ph1ent['ikeid']}000\n";
1451
				}
1452
				//if (!empty($reqids[$idx])) {
1453
				//	$ipsecfin .= "\treqid = " . $reqids[0] . "\n";
1454
				//}
1455
				$rightadd = "";
1456
				$leftadd = "";
1457
				if (!empty($vtireq[0])) {
1458
					$ipsecfin .= "\treqid = {$ph1ent['ikeid']}000\n";
1459
					/* This interface will be a valid IPsec interface, so remove it from the cleanup list. */
1460
					$ipsec_vti_cleanup_ifs = array_diff($ipsec_vti_cleanup_ifs, array("ipsec{$ph1ent['ikeid']}000"));
1461
					$rightadd = ",0.0.0.0/0";
1462
					$leftadd = ",0.0.0.0/0";
1463
				}
1464
				$ipsecfin .= $ipsecconnect;
1465
				if (!isset($ph1ent['mobile']) && !empty($rightsubnet_spec)) {
1466
					$tempsubnets = array();
1467
					foreach ($rightsubnet_spec as $rightsubnet) {
1468
						$tempsubnets[$rightsubnet] = $rightsubnet;
1469
					}
1470
					$ipsecfin .= "\trightsubnet = " . join(",", $tempsubnets) . "{$rightadd}\n";
1471
					unset($tempsubnets, $rightsubnet);
1472
				}
1473
				if (!empty($leftsubnet_spec)) {
1474
					$tempsubnets = array();
1475
					foreach ($leftsubnet_spec as $leftsubnet) {
1476
						$tempsubnets[$leftsubnet] = $leftsubnet;
1477
					}
1478
					$ipsecfin .= "\tleftsubnet = " . join(",", $tempsubnets) . "{$leftadd}\n";
1479
					unset($tempsubnets, $leftsubnet);
1480
				}
1481
			}
1482
			$ipsecconf .= $ipsecfin;
1483
			unset($ipsecfin);
1484
		}
1485
	}
1486

    
1487
	$a_mobilekey = $config['ipsec']['mobilekey'];
1488

    
1489
	if (is_array($a_phase1) && count($a_phase1)) {
1490
		foreach ($a_phase1 as $ph1ent) {
1491
			if (!isset($ph1ent['mobile'])) {
1492
				continue;
1493
			}
1494
			if (isset($ph1ent['disabled'])) {
1495
				continue;
1496
			}
1497

    
1498
			if (is_array($a_mobilekey) && count($a_mobilekey)) {
1499
				$ipsecfin = '';
1500
				$mobilekey_counter = 1;
1501
				foreach ($a_mobilekey as $mkent) {
1502
					if ($mkent['type'] != "EAP") {
1503
						continue;
1504
					}
1505

    
1506
					if (!isset($mkent['ident_type']) || !isset($mkent['pool_address']) || !isset($mkent['pool_netbits'])) {
1507
						continue;
1508
					}
1509

    
1510
					if (strlen($mkent['pool_address']) < 1 || !is_ipaddr($mkent['pool_address'])) {
1511
						continue;
1512
					}
1513
					$clientid = ($mkent['ident_type'] == "none") ? "\"{$mkent['ident']}\"" : "{$mkent['ident_type']}:{$mkent['ident']}";
1514
					$clienteapid = ($ph1ent['authentication_method'] == "eap-mschapv2") ? $clientid : '%identity';
1515
					$ipsecfin .= "\nconn mobile-{$mobilekey_counter}\n";
1516
					$ipsecfin .= "\talso = con-mobile\n";
1517
					$ipsecfin .= "\teap_identity = {$clienteapid}\n";
1518
					$ipsecfin .= "\trightsourceip = {$mkent['pool_address']}/{$mkent['pool_netbits']}\n";
1519

    
1520
					if (isset($mkent['dns_address']) && strlen($mkent['dns_address']) > 0 && is_ipaddr($mkent['dns_address'])) {
1521
						$ipsecfin .= "\trightdns = {$mkent['dns_address']}\n";
1522
					}
1523

    
1524
					$ipsecfin .= "\trightid = {$clientid}\n";
1525

    
1526
					// optional: define left|rightid more granular
1527
					// supported: ipv4, ipv6, rfc822, email, userfqdn, fqdn, dns, asn1dn, asn1gn, keyid
1528
					// example: $ipsecfin = "\trightid = email:your@email.address\n";
1529

    
1530
					// note: comma seperated list for access restriction, regardless of firewall rules
1531
					// example: $ipsecfin = "\tleftsubnet = 1.1.1.1/32,1.1.1.2/32,2.2.2.0/24\n";
1532

    
1533
					$mobilekey_counter++;
1534
				}
1535
				$ipsecconf .= $ipsecfin;
1536
				unset($ipsecfin);
1537
				unset($mobilekey_counter);
1538
			}
1539
		}
1540
	}
1541

    
1542
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.conf", $ipsecconf);
1543
	unset($ipsecconf);
1544
	/* end ipsec.conf */
1545

    
1546
	foreach ($ipsec_vti_cleanup_ifs as $cleanif) {
1547
		if (does_interface_exist($cleanif)) {
1548
			mwexec("/sbin/ifconfig " . escapeshellarg($cleanif) . " destroy", false);
1549
		}
1550
	}
1551

    
1552
	if ($enablecompression === true) {
1553
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 1);
1554
	} else {
1555
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 0);
1556
	}
1557

    
1558
	/* manage process */
1559
	if ($restart === true) {
1560
		mwexec("/usr/local/sbin/ipsec restart", false);
1561
	} else {
1562
		if (isvalidpid("{$g['varrun_path']}/starter.charon.pid")) {
1563
			/* Update configuration changes */
1564
			/* Read secrets */
1565
			mwexec("/usr/local/sbin/ipsec rereadall", false);
1566
			mwexec("/usr/local/sbin/ipsec reload", false);
1567
		} else {
1568
			mwexec("/usr/local/sbin/ipsec start", false);
1569
		}
1570
	}
1571

    
1572
	// run ping_hosts.sh once if it's enabled to avoid wait for minicron
1573
	if ($ipsecpinghostsactive == true) {
1574
		mwexec_bg("/usr/local/bin/ping_hosts.sh");
1575
	}
1576

    
1577
	if ($natfilterrules == true) {
1578
		filter_configure();
1579
	}
1580
	/* start filterdns, if necessary */
1581
	if (count($filterdns_list) > 0) {
1582
		$interval = 60;
1583
		if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval'])) {
1584
			$interval = $ipseccfg['dns-interval'];
1585
		}
1586

    
1587
		$hostnames = "";
1588
		array_unique($filterdns_list);
1589
		foreach ($filterdns_list as $hostname) {
1590
			$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
1591
		}
1592
		file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
1593
		unset($hostnames);
1594

    
1595
		if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid")) {
1596
			sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
1597
		} else {
1598
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
1599
		}
1600
	} else {
1601
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
1602
		@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
1603
	}
1604

    
1605
	if (platform_booting()) {
1606
		echo "done\n";
1607
	}
1608

    
1609
	unlock($ipsecstartlock);
1610
	return count($filterdns_list);
1611
}
1612

    
1613
/*
1614
 * Forcefully restart IPsec
1615
 * This is required for when dynamic interfaces reload
1616
 * For all other occasions the normal vpn_ipsec_configure()
1617
 * will gracefully reload the settings without restarting
1618
 */
1619
function vpn_ipsec_force_reload($interface = "") {
1620
	global $g, $config;
1621

    
1622
	if (!ipsec_enabled()) {
1623
		return;
1624
	}
1625

    
1626
	$ipseccfg = $config['ipsec'];
1627

    
1628
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1629
		$found = false;
1630
		foreach ($ipseccfg['phase1'] as $ipsec) {
1631
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1632
				$found = true;
1633
				break;
1634
			}
1635
		}
1636
		if (!$found) {
1637
			log_error(sprintf(gettext("Ignoring IPsec reload since there are no tunnels on interface %s"), $interface));
1638
			return;
1639
		}
1640
	}
1641

    
1642
	/* If we get this far then we need to take action. */
1643
	log_error(gettext("Forcefully reloading IPsec"));
1644
	vpn_ipsec_configure();
1645
}
1646

    
1647
/* master setup for vpn (mpd) */
1648
function vpn_setup() {
1649
	/* start pppoe server */
1650
	vpn_pppoes_configure();
1651

    
1652
	/* setup l2tp */
1653
	vpn_l2tp_configure();
1654
}
1655

    
1656
function vpn_netgraph_support() {
1657
	$iflist = get_configured_interface_list();
1658
	foreach ($iflist as $iface) {
1659
		$realif = get_real_interface($iface);
1660
		/* Get support for netgraph(4) from the nic */
1661
		$ifinfo = pfSense_get_interface_addresses($realif);
1662
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge"))) {
1663
			pfSense_ngctl_attach(".", $realif);
1664
		}
1665
	}
1666
}
1667

    
1668
function vpn_pppoes_configure() {
1669
	global $config;
1670

    
1671
	if (is_array($config['pppoes']['pppoe'])) {
1672
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
1673
			vpn_pppoe_configure($pppoe);
1674
		}
1675
	}
1676
}
1677

    
1678
function vpn_pppoe_configure(&$pppoecfg) {
1679
	global $config, $g;
1680

    
1681
	$syscfg = $config['system'];
1682

    
1683
	/* create directory if it does not exist */
1684
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
1685
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1686
	}
1687

    
1688
	if (platform_booting()) {
1689
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
1690
			return 0;
1691
		}
1692

    
1693
		echo gettext("Configuring PPPoE Server service... ");
1694
	} else {
1695
		/* kill mpd */
1696
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1697

    
1698
		/* wait for process to die */
1699
		sleep(2);
1700

    
1701
	}
1702

    
1703
	switch ($pppoecfg['mode']) {
1704

    
1705
		case 'server':
1706

    
1707
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1708

    
1709
			if ($pppoecfg['paporchap'] == "chap") {
1710
				$paporchap = "set link enable chap";
1711
			} else {
1712
				$paporchap = "set link enable pap";
1713
			}
1714

    
1715
			/* write mpd.conf */
1716
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1717
			if (!$fd) {
1718
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1719
				return 1;
1720
			}
1721

    
1722
			$issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 ";
1723
			if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1724
				$issue_ip_type .= "0.0.0.0/0";
1725
			} else {
1726
				$issue_ip_type .= "ippool p0";
1727
			}
1728

    
1729
			$ippool_p0 = ip_after($pppoecfg['remoteip'], $pppoecfg['n_pppoe_units'] - 1);
1730

    
1731
			if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
1732
				$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
1733
			} else {
1734
				$pppoemaxlogins = 1;
1735
			}
1736

    
1737
			$ipcp_dns = '';
1738
			if (!empty($pppoecfg['dns1'])) {
1739
				$ipcp_dns = "set ipcp dns " . $pppoecfg['dns1'];
1740
				if (!empty($pppoecfg['dns2'])) {
1741
					$ipcp_dns .= " " . $pppoecfg['dns2'];
1742
				}
1743
			} elseif (isset($config['dnsmasq']['enable']) ||
1744
			    isset ($config['unbound']['enable'])) {
1745
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1746
				if ($syscfg['dnsserver'][0]) {
1747
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1748
				}
1749
			} elseif (is_array($syscfg['dnsserver']) &&
1750
			    ($syscfg['dnsserver'][0])) {
1751
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1752
			}
1753

    
1754
			$mpdconf = <<<EOD
1755
startup:
1756

    
1757
poes:
1758
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
1759

    
1760
	create bundle template poes_b
1761
	set bundle enable compression
1762

    
1763
	set ccp yes mppc
1764
	set mppc yes e40
1765
	set mppc yes e128
1766
	set mppc yes stateless
1767

    
1768
	set iface group pppoe
1769
	set iface up-script /usr/local/sbin/vpn-linkup-poes
1770
	set iface down-script /usr/local/sbin/vpn-linkdown-poes
1771
	set iface idle 0
1772
	set iface disable on-demand
1773
	set iface disable proxy-arp
1774
	set iface enable tcpmssfix
1775
	set iface mtu 1500
1776

    
1777
	set ipcp no vjcomp
1778
	{$issue_ip_type}
1779
	{$ipcp_dns}
1780

    
1781
	create link template poes_l pppoe
1782
	set link action bundle poes_b
1783

    
1784
	set auth max-logins {$pppoemaxlogins}
1785

    
1786
	set pppoe iface {$pppoe_interface}
1787

    
1788
	set link no multilink
1789
	set link no pap chap
1790
	{$paporchap}
1791
	set link keep-alive 60 180
1792
	set link max-redial -1
1793
	set link mru 1492
1794
	set link latency 1
1795
	set link enable incoming
1796

    
1797
EOD;
1798

    
1799
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1800
				$radiusport = "";
1801
				$radiusacctport = "";
1802
				if (isset($pppoecfg['radius']['server']['port'])) {
1803
					$radiusport = $pppoecfg['radius']['server']['port'];
1804
				}
1805
				if (isset($pppoecfg['radius']['server']['acctport'])) {
1806
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1807
				}
1808
				$mpdconf .=<<<EOD
1809
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1810
	set radius retries 3
1811
	set radius timeout 10
1812
	set auth enable radius-auth
1813

    
1814
EOD;
1815

    
1816
				if (isset ($pppoecfg['radius']['accounting'])) {
1817
					$mpdconf .=<<<EOD
1818
	set auth enable radius-acct
1819

    
1820
EOD;
1821
				}
1822
				if (!empty($pppoecfg['radius']['nasip'])) {
1823
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
1824
				}
1825
			}
1826

    
1827
			fwrite($fd, $mpdconf);
1828
			fclose($fd);
1829
			unset($mpdconf);
1830

    
1831
			if ($pppoecfg['username']) {
1832
				/* write mpd.secret */
1833
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1834
				if (!$fd) {
1835
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1836
					return 1;
1837
				}
1838

    
1839
				$mpdsecret = "\n\n";
1840

    
1841
				if (!empty($pppoecfg['username'])) {
1842
					$item = explode(" ", $pppoecfg['username']);
1843
					foreach ($item as $userdata) {
1844
						$data = explode(":", $userdata);
1845
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1846
					}
1847
				}
1848

    
1849
				fwrite($fd, $mpdsecret);
1850
				fclose($fd);
1851
				unset($mpdsecret);
1852
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1853
			}
1854

    
1855
			/* Check if previous instance is still up */
1856
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
1857
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1858
			}
1859

    
1860
			/* Get support for netgraph(4) from the nic */
1861
			pfSense_ngctl_attach(".", $pppoe_interface);
1862
			/* fire up mpd */
1863
			mwexec("/usr/local/sbin/mpd5 -b -d {$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn -p {$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid -s poes poes");
1864

    
1865
			break;
1866
	}
1867

    
1868
	if (platform_booting()) {
1869
		echo gettext("done") . "\n";
1870
	}
1871

    
1872
	return 0;
1873
}
1874

    
1875
function vpn_l2tp_configure() {
1876
	global $config, $g;
1877

    
1878
	$syscfg = $config['system'];
1879
	$l2tpcfg = $config['l2tp'];
1880

    
1881
	/* create directory if it does not exist */
1882
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
1883
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1884
	}
1885

    
1886
	if (platform_booting()) {
1887
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
1888
			return 0;
1889
		}
1890

    
1891
		echo gettext("Configuring l2tp VPN service... ");
1892
	} else {
1893
		/* kill mpd */
1894
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1895

    
1896
		/* wait for process to die */
1897
		sleep(8);
1898

    
1899
	}
1900

    
1901
	/* make sure l2tp-vpn directory exists */
1902
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn")) {
1903
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1904
	}
1905

    
1906
	switch ($l2tpcfg['mode']) {
1907

    
1908
		case 'server':
1909
			$l2tp_listen="";
1910
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
1911
			if (is_ipaddrv4($ipaddr)) {
1912
				$l2tp_listen="set l2tp self $ipaddr";
1913
			}
1914

    
1915
			switch ($l2tpcfg['paporchap']) {
1916
				case 'chap':
1917
					$paporchap = "set link enable chap";
1918
					break;
1919
				case 'chap-msv2':
1920
					$paporchap = "set link enable chap-msv2";
1921
					break;
1922
				default:
1923
					$paporchap = "set link enable pap";
1924
					break;
1925
			}
1926

    
1927
			/* write mpd.conf */
1928
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1929
			if (!$fd) {
1930
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1931
				return 1;
1932
			}
1933

    
1934
			$ippool_p0 = ip_after($l2tpcfg['remoteip'], $l2tpcfg['n_l2tp_units'] - 1);
1935

    
1936
			$issue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 ";
1937
			if (isset($l2tpcfg['radius']['radiusissueips']) && isset($l2tpcfg['radius']['server']['enable'])) {
1938
				$issue_ip_type .= "0.0.0.0/0";
1939
			} else {
1940
				$issue_ip_type .= "ippool p0";
1941
			}
1942

    
1943
			$ipcp_dns = '';
1944
			if (is_ipaddr($l2tpcfg['dns1'])) {
1945
				$ipcp_dns = "set ipcp dns " . $l2tpcfg['dns1'];
1946
				if (is_ipaddr($l2tpcfg['dns2'])) {
1947
					$ipcp_dns .= " " . $l2tpcfg['dns2'];
1948
				}
1949
			} elseif (isset ($config['dnsmasq']['enable']) ||
1950
			    isset ($config['unbound']['enable'])) {
1951
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1952
				if ($syscfg['dnsserver'][0]) {
1953
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1954
				}
1955
			} elseif (is_array($syscfg['dnsserver']) &&
1956
			    ($syscfg['dnsserver'][0])) {
1957
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1958
			}
1959

    
1960
			$mpdconf =<<<EOD
1961

    
1962
startup:
1963

    
1964
l2tps:
1965
	set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}
1966

    
1967
	create bundle template l2tp_b
1968
	set bundle enable compression
1969
	set bundle yes crypt-reqd
1970

    
1971
	set ccp yes mppc
1972

    
1973
	set iface name l2tp
1974
	set iface group l2tp
1975
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
1976
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
1977
	set iface disable on-demand
1978
	set iface enable proxy-arp
1979

    
1980
	set ipcp yes vjcomp
1981
	{$issue_ip_type}
1982
	{$ipcp_dns}
1983

    
1984
	create link template l2tp_l l2tp
1985
	set link action bundle l2tp_b
1986

    
1987
	set link yes acfcomp protocomp
1988
	set link enable multilink
1989
	set link no pap chap chap-msv2
1990
	{$paporchap}
1991
	{$l2tp_listen}
1992
	set link keep-alive 10 180
1993
	set link enable incoming
1994

    
1995
EOD;
1996

    
1997

    
1998
			if (isset ($l2tpcfg['radius']['enable'])) {
1999
				$mpdconf .=<<<EOD
2000
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
2001
	set radius retries 3
2002
	set radius timeout 10
2003
	set auth disable internal
2004
	set auth enable radius-auth
2005

    
2006
EOD;
2007

    
2008
				if (isset ($l2tpcfg['radius']['accounting'])) {
2009
					$mpdconf .=<<<EOD
2010
	set auth enable radius-acct
2011

    
2012
EOD;
2013
				}
2014
			}
2015

    
2016
			fwrite($fd, $mpdconf);
2017
			fclose($fd);
2018
			unset($mpdconf);
2019

    
2020
			/* write mpd.secret */
2021
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
2022
			if (!$fd) {
2023
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
2024
				return 1;
2025
			}
2026

    
2027
			$mpdsecret = "\n\n";
2028

    
2029
			if (is_array($l2tpcfg['user'])) {
2030
				foreach ($l2tpcfg['user'] as $user) {
2031
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
2032
				}
2033
			}
2034

    
2035
			fwrite($fd, $mpdsecret);
2036
			fclose($fd);
2037
			unset($mpdsecret);
2038
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
2039

    
2040
			vpn_netgraph_support();
2041

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

    
2045
			break;
2046

    
2047
		case 'redir':
2048
			break;
2049
	}
2050

    
2051
	if (platform_booting()) {
2052
		echo "done\n";
2053
	}
2054

    
2055
	return 0;
2056
}
2057

    
2058
?>
(54-54/60)