Project

General

Profile

Download (59.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * vpn.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2018 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
						if (!empty($vtireq[$idx])) {
1430
							$ipsecfin .= "\treqid = {$ph1ent['ikeid']}00{$idx}\n";
1431
							/* This interface will be a valid IPsec interface, so remove it from the cleanup list. */
1432
							$ipsec_vti_cleanup_ifs = array_diff($ipsec_vti_cleanup_ifs, array("ipsec{$ph1ent['ikeid']}00{$idx}"));
1433
						}
1434
						$ipsecfin .= $ipsecconnect;
1435
						$ipsecfin .= "\trightsubnet = {$rsubnet}\n";
1436
						$ipsecfin .= "\tleftsubnet = " . $leftsubnet_spec[$idx] . "\n";
1437
					}
1438
				} else {
1439
					log_error(sprintf(gettext("No phase2 specifications for tunnel with REQID = %s"), $ikeid));
1440
				}
1441
			} else {
1442
				if (isset($ph1ent['mobile'])) {
1443
					$ipsecfin = "\nconn con-mobile\n";
1444
				}
1445
				else {
1446
					$ipsecfin = "\nconn con{$ph1ent['ikeid']}000\n";
1447
				}
1448
				//if (!empty($reqids[$idx])) {
1449
				//	$ipsecfin .= "\treqid = " . $reqids[0] . "\n";
1450
				//}
1451
				if (!empty($vtireq[0])) {
1452
					$ipsecfin .= "\treqid = {$ph1ent['ikeid']}000\n";
1453
					/* This interface will be a valid IPsec interface, so remove it from the cleanup list. */
1454
					$ipsec_vti_cleanup_ifs = array_diff($ipsec_vti_cleanup_ifs, array("ipsec{$ph1ent['ikeid']}000"));
1455
				}
1456
				$ipsecfin .= $ipsecconnect;
1457
				if (!isset($ph1ent['mobile']) && !empty($rightsubnet_spec)) {
1458
					$tempsubnets = array();
1459
					foreach ($rightsubnet_spec as $rightsubnet) {
1460
						$tempsubnets[$rightsubnet] = $rightsubnet;
1461
					}
1462
					$ipsecfin .= "\trightsubnet = " . join(",", $tempsubnets) . "\n";
1463
					unset($tempsubnets, $rightsubnet);
1464
				}
1465
				if (!empty($leftsubnet_spec)) {
1466
					$tempsubnets = array();
1467
					foreach ($leftsubnet_spec as $leftsubnet) {
1468
						$tempsubnets[$leftsubnet] = $leftsubnet;
1469
					}
1470
					$ipsecfin .= "\tleftsubnet = " . join(",", $tempsubnets) . "\n";
1471
					unset($tempsubnets, $leftsubnet);
1472
				}
1473
			}
1474
			$ipsecconf .= $ipsecfin;
1475
			unset($ipsecfin);
1476
		}
1477
	}
1478

    
1479
	$a_mobilekey = $config['ipsec']['mobilekey'];
1480

    
1481
	if (is_array($a_phase1) && count($a_phase1)) {
1482
		foreach ($a_phase1 as $ph1ent) {
1483
			if (!isset($ph1ent['mobile'])) {
1484
				continue;
1485
			}
1486
			if (isset($ph1ent['disabled'])) {
1487
				continue;
1488
			}
1489

    
1490
			if (is_array($a_mobilekey) && count($a_mobilekey)) {
1491
				$ipsecfin = '';
1492
				$mobilekey_counter = 1;
1493
				foreach ($a_mobilekey as $mkent) {
1494
					if ($mkent['type'] != "EAP") {
1495
						continue;
1496
					}
1497

    
1498
					if (!isset($mkent['ident_type']) || !isset($mkent['pool_address']) || !isset($mkent['pool_netbits'])) {
1499
						continue;
1500
					}
1501

    
1502
					if (strlen($mkent['pool_address']) < 1 || !is_ipaddr($mkent['pool_address'])) {
1503
						continue;
1504
					}
1505

    
1506
					$ipsecfin .= "\nconn mobile-{$mobilekey_counter}\n";
1507
					$ipsecfin .= "\talso = con-mobile\n";
1508
					$ipsecfin .= "\teap_identity = %identity\n";
1509
					$ipsecfin .= "\trightsourceip = {$mkent['pool_address']}/{$mkent['pool_netbits']}\n";
1510

    
1511
					if (isset($mkent['dns_address']) && strlen($mkent['dns_address']) > 0 && is_ipaddr($mkent['dns_address'])) {
1512
						$ipsecfin .= "\trightdns = {$mkent['dns_address']}\n";
1513
					}
1514

    
1515
					if ($mkent['ident_type'] == "none") {
1516
						$ipsecfin .= "\trightid = \"{$mkent['ident']}\"\n";
1517
					}
1518
					else {
1519
						$ipsecfin .= "\trightid = {$mkent['ident_type']}:{$mkent['ident']}\n";
1520
					}
1521

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

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

    
1529
					$mobilekey_counter++;
1530
				}
1531
				$ipsecconf .= $ipsecfin;
1532
				unset($ipsecfin);
1533
				unset($mobilekey_counter);
1534
			}
1535
		}
1536
	}
1537

    
1538
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.conf", $ipsecconf);
1539
	unset($ipsecconf);
1540
	/* end ipsec.conf */
1541

    
1542
	foreach ($ipsec_vti_cleanup_ifs as $cleanif) {
1543
		if (does_interface_exist($cleanif)) {
1544
			mwexec("/sbin/ifconfig " . escapeshellarg($cleanif) . " destroy", false);
1545
		}
1546
	}
1547

    
1548
	if ($enablecompression === true) {
1549
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 1);
1550
	} else {
1551
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 0);
1552
	}
1553

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

    
1568
	// run ping_hosts.sh once if it's enabled to avoid wait for minicron
1569
	if ($ipsecpinghostsactive == true) {
1570
		mwexec_bg("/usr/local/bin/ping_hosts.sh");
1571
	}
1572

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

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

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

    
1601
	if (platform_booting()) {
1602
		echo "done\n";
1603
	}
1604

    
1605
	unlock($ipsecstartlock);
1606
	return count($filterdns_list);
1607
}
1608

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

    
1618
	if (!ipsec_enabled()) {
1619
		return;
1620
	}
1621

    
1622
	$ipseccfg = $config['ipsec'];
1623

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

    
1638
	/* If we get this far then we need to take action. */
1639
	log_error(gettext("Forcefully reloading IPsec"));
1640
	vpn_ipsec_configure();
1641
}
1642

    
1643
/* master setup for vpn (mpd) */
1644
function vpn_setup() {
1645
	/* start pppoe server */
1646
	vpn_pppoes_configure();
1647

    
1648
	/* setup l2tp */
1649
	vpn_l2tp_configure();
1650
}
1651

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

    
1664
function vpn_pppoes_configure() {
1665
	global $config;
1666

    
1667
	if (is_array($config['pppoes']['pppoe'])) {
1668
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
1669
			vpn_pppoe_configure($pppoe);
1670
		}
1671
	}
1672
}
1673

    
1674
function vpn_pppoe_configure(&$pppoecfg) {
1675
	global $config, $g;
1676

    
1677
	$syscfg = $config['system'];
1678

    
1679
	/* create directory if it does not exist */
1680
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
1681
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1682
	}
1683

    
1684
	if (platform_booting()) {
1685
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
1686
			return 0;
1687
		}
1688

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

    
1694
		/* wait for process to die */
1695
		sleep(2);
1696

    
1697
	}
1698

    
1699
	switch ($pppoecfg['mode']) {
1700

    
1701
		case 'server':
1702

    
1703
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1704

    
1705
			if ($pppoecfg['paporchap'] == "chap") {
1706
				$paporchap = "set link enable chap";
1707
			} else {
1708
				$paporchap = "set link enable pap";
1709
			}
1710

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

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

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

    
1727
			if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
1728
				$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
1729
			} else {
1730
				$pppoemaxlogins = 1;
1731
			}
1732

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

    
1750
			$mpdconf = <<<EOD
1751
startup:
1752

    
1753
poes:
1754
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
1755

    
1756
	create bundle template poes_b
1757
	set bundle enable compression
1758

    
1759
	set ccp yes mppc
1760
	set mppc yes e40
1761
	set mppc yes e128
1762
	set mppc yes stateless
1763

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

    
1773
	set ipcp no vjcomp
1774
	{$issue_ip_type}
1775
	{$ipcp_dns}
1776

    
1777
	create link template poes_l pppoe
1778
	set link action bundle poes_b
1779

    
1780
	set auth max-logins {$pppoemaxlogins}
1781

    
1782
	set pppoe iface {$pppoe_interface}
1783

    
1784
	set link no multilink
1785
	set link no pap chap
1786
	{$paporchap}
1787
	set link keep-alive 60 180
1788
	set link max-redial -1
1789
	set link mru 1492
1790
	set link latency 1
1791
	set link enable incoming
1792

    
1793
EOD;
1794

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

    
1810
EOD;
1811

    
1812
				if (isset ($pppoecfg['radius']['accounting'])) {
1813
					$mpdconf .=<<<EOD
1814
	set auth enable radius-acct
1815

    
1816
EOD;
1817
				}
1818
				if (!empty($pppoecfg['radius']['nasip'])) {
1819
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
1820
				}
1821
			}
1822

    
1823
			fwrite($fd, $mpdconf);
1824
			fclose($fd);
1825
			unset($mpdconf);
1826

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

    
1835
				$mpdsecret = "\n\n";
1836

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

    
1845
				fwrite($fd, $mpdsecret);
1846
				fclose($fd);
1847
				unset($mpdsecret);
1848
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1849
			}
1850

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

    
1856
			/* Get support for netgraph(4) from the nic */
1857
			pfSense_ngctl_attach(".", $pppoe_interface);
1858
			/* fire up mpd */
1859
			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");
1860

    
1861
			break;
1862
	}
1863

    
1864
	if (platform_booting()) {
1865
		echo gettext("done") . "\n";
1866
	}
1867

    
1868
	return 0;
1869
}
1870

    
1871
function vpn_l2tp_configure() {
1872
	global $config, $g;
1873

    
1874
	$syscfg = $config['system'];
1875
	$l2tpcfg = $config['l2tp'];
1876

    
1877
	/* create directory if it does not exist */
1878
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
1879
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1880
	}
1881

    
1882
	if (platform_booting()) {
1883
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
1884
			return 0;
1885
		}
1886

    
1887
		echo gettext("Configuring l2tp VPN service... ");
1888
	} else {
1889
		/* kill mpd */
1890
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1891

    
1892
		/* wait for process to die */
1893
		sleep(8);
1894

    
1895
	}
1896

    
1897
	/* make sure l2tp-vpn directory exists */
1898
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn")) {
1899
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1900
	}
1901

    
1902
	switch ($l2tpcfg['mode']) {
1903

    
1904
		case 'server':
1905
			$l2tp_listen="";
1906
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
1907
			if (is_ipaddrv4($ipaddr)) {
1908
				$l2tp_listen="set l2tp self $ipaddr";
1909
			}
1910

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

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

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

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

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

    
1956
			$mpdconf =<<<EOD
1957

    
1958
startup:
1959

    
1960
l2tps:
1961
	set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}
1962

    
1963
	create bundle template l2tp_b
1964
	set bundle enable compression
1965
	set bundle yes crypt-reqd
1966

    
1967
	set ccp yes mppc
1968

    
1969
	set iface name l2tp
1970
	set iface group l2tp
1971
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
1972
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
1973
	set iface disable on-demand
1974
	set iface enable proxy-arp
1975

    
1976
	set ipcp yes vjcomp
1977
	{$issue_ip_type}
1978
	{$ipcp_dns}
1979

    
1980
	create link template l2tp_l l2tp
1981
	set link action bundle l2tp_b
1982

    
1983
	set link yes acfcomp protocomp
1984
	set link enable multilink
1985
	set link no pap chap chap-msv2
1986
	{$paporchap}
1987
	{$l2tp_listen}
1988
	set link keep-alive 10 180
1989
	set link enable incoming
1990

    
1991
EOD;
1992

    
1993

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

    
2002
EOD;
2003

    
2004
				if (isset ($l2tpcfg['radius']['accounting'])) {
2005
					$mpdconf .=<<<EOD
2006
	set auth enable radius-acct
2007

    
2008
EOD;
2009
				}
2010
			}
2011

    
2012
			fwrite($fd, $mpdconf);
2013
			fclose($fd);
2014
			unset($mpdconf);
2015

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

    
2023
			$mpdsecret = "\n\n";
2024

    
2025
			if (is_array($l2tpcfg['user'])) {
2026
				foreach ($l2tpcfg['user'] as $user) {
2027
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
2028
				}
2029
			}
2030

    
2031
			fwrite($fd, $mpdsecret);
2032
			fclose($fd);
2033
			unset($mpdsecret);
2034
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
2035

    
2036
			vpn_netgraph_support();
2037

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

    
2041
			break;
2042

    
2043
		case 'redir':
2044
			break;
2045
	}
2046

    
2047
	if (platform_booting()) {
2048
		echo "done\n";
2049
	}
2050

    
2051
	return 0;
2052
}
2053

    
2054
?>
(54-54/60)