Project

General

Profile

Download (55.2 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
	if (!ipsec_enabled()) {
138
		/* try to stop charon */
139
		mwexec("/usr/local/sbin/ipsec stop");
140
		/* Stop dynamic monitoring */
141
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
142

    
143
		/* wait for process to die */
144
		sleep(2);
145

    
146
		/* IPSEC is off, shutdown enc interface.*/
147
		mwexec("/sbin/ifconfig enc0 down");
148

    
149
		unlock($ipsecstartlock);
150
		return 0;
151
	}
152

    
153
	$a_phase1 = $config['ipsec']['phase1'];
154
	$a_phase2 = $config['ipsec']['phase2'];
155
	$a_client = $config['ipsec']['client'];
156

    
157
	$certpath = "{$g['varetc_path']}/ipsec/ipsec.d/certs";
158
	$capath = "{$g['varetc_path']}/ipsec/ipsec.d/cacerts";
159
	$keypath = "{$g['varetc_path']}/ipsec/ipsec.d/private";
160
	$crlpath = "{$g['varetc_path']}/ipsec/ipsec.d/crls";
161

    
162
	mwexec("/sbin/ifconfig enc0 up");
163

    
164
	/* needed for config files */
165
	if (!is_dir("{$g['varetc_path']}/ipsec")) {
166
		mkdir("{$g['varetc_path']}/ipsec");
167
	}
168
	if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d")) {
169
		mkdir("{$g['varetc_path']}/ipsec/ipsec.d");
170
	}
171
	// delete these paths first to ensure old CAs, certs and CRLs aren't left behind. redmine #5238
172
	rmdir_recursive($capath);
173
	rmdir_recursive($keypath);
174
	rmdir_recursive($crlpath);
175
	rmdir_recursive($certpath);
176
	if (!is_dir($capath)) {
177
		mkdir($capath);
178
	}
179
	if (!is_dir($keypath)) {
180
		mkdir($keypath);
181
	}
182
	if (!is_dir($crlpath)) {
183
		mkdir($crlpath);
184
	}
185
	if (!is_dir($certpath)) {
186
		mkdir($certpath);
187
	}
188
	if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/aacerts")) {
189
		mkdir("{$g['varetc_path']}/ipsec/ipsec.d/aacerts");
190
	}
191
	if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/acerts")) {
192
		mkdir("{$g['varetc_path']}/ipsec/ipsec.d/acerts");
193
	}
194
	if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/ocspcerts")) {
195
		mkdir("{$g['varetc_path']}/ipsec/ipsec.d/ocspcerts");
196
	}
197
	if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/reqs")) {
198
		mkdir("{$g['varetc_path']}/ipsec/ipsec.d/reqs");
199
	}
200

    
201
	if (!file_exists("/usr/local/etc/ipsec.d") ||
202
	    !is_link("/usr/local/etc/ipsec.d")) {
203
		if (file_exists("/usr/local/etc/ipsec.d")) {
204
			rmdir_recursive("/usr/local/etc/ipsec.d");
205
		}
206
		@symlink("{$g['varetc_path']}/ipsec/ipsec.d",
207
		    "/usr/local/etc/ipsec.d");
208
	}
209
	if (!file_exists("{$g['varetc_path']}/etc/strongswan.d") ||
210
	    !is_link("{$g['varetc_path']}/etc/strongswan.d")) {
211
		if (is_link("{$g['varetc_path']}/etc/strongswan.d")) {
212
			@unlink("{$g['varetc_path']}/etc/strongswan.d");
213
		} else {
214
			rmdir_recursive("{$g['varetc_path']}/etc/strongswan.d");
215
		}
216
		@symlink("/usr/local/etc/strongswan.d",
217
		    "{$g['varetc_path']}/ipsec/strongswan.d");
218
	}
219
	if (!file_exists("/usr/local/etc/strongswan.conf") ||
220
	    !is_link("/usr/local/etc/strongswan.conf")) {
221
		@unlink("/usr/local/etc/strongswan.conf");
222
		@symlink("{$g['varetc_path']}/ipsec/strongswan.conf",
223
		    "/usr/local/etc/strongswan.conf");
224
	}
225
	if (!file_exists("/usr/local/etc/ipsec.conf") ||
226
	    !is_link("/usr/local/etc/ipsec.conf")) {
227
		@unlink("/usr/local/etc/ipsec.conf");
228
		@symlink("{$g['varetc_path']}/ipsec/ipsec.conf",
229
		    "/usr/local/etc/ipsec.conf");
230
	}
231

    
232
	if (platform_booting()) {
233
		echo gettext("Configuring IPsec VPN... ");
234
	}
235

    
236
	/* resolve all local, peer addresses and setup pings */
237
	$ipmap = array();
238
	$rgmap = array();
239
	$filterdns_list = array();
240
	$aggressive_mode_psk = false;
241
	unset($iflist);
242
	$ifacesuse = array();
243
	$mobile_ipsec_auth = "";
244
	if (is_array($a_phase1) && count($a_phase1)) {
245

    
246
		$ipsecpinghosts = "";
247
		/* step through each phase1 entry */
248
		foreach ($a_phase1 as $ph1ent) {
249
			if (isset($ph1ent['disabled'])) {
250
				continue;
251
			}
252

    
253
			if (substr($ph1ent['interface'], 0, 4) == "_vip") {
254
				$vpninterface = get_configured_vip_interface($ph1ent['interface']);
255
				$ifacesuse[] = get_real_interface($vpninterface);
256
			} else {
257
				$vpninterface = get_failover_interface($ph1ent['interface']);
258
				if (substr($vpninterface, 0, 4) == "_vip") {
259
					$vpninterface = get_configured_vip_interface($vpninterface);
260
					$ifacesuse[] = get_real_interface($vpninterface);
261
				} elseif (!empty($vpninterface)) {
262
					$ifacesuse[] = $vpninterface;
263
				}
264
			}
265

    
266
			if ($ph1ent['mode'] == "aggressive" && ($ph1ent['authentication_method'] == "pre_shared_key" || $ph1ent['authentication_method'] == "xauth_psk_server")) {
267
				$aggressive_mode_psk = true;
268
			}
269

    
270
			$ikeid = $ph1ent['ikeid'];
271

    
272
			$ep = ipsec_get_phase1_src($ph1ent);
273
			if (!is_ipaddr($ep)) {
274
				log_error(sprintf(gettext("IPsec ERROR: Could not find phase 1 source for connection %s. Omitting from configuration file."), $ph1ent['descr']));
275
				continue;
276
			}
277

    
278
			if (!in_array($ep, $ipmap)) {
279
				$ipmap[] = $ep;
280
			}
281

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

    
285
			if (isset ($ph1ent['mobile'])) {
286
				$mobile_ipsec_auth = $ph1ent['authentication_method'];
287
				continue;
288
			}
289

    
290
			$rg = $ph1ent['remote-gateway'];
291

    
292
			if (!is_ipaddr($rg)) {
293
				$filterdns_list[] = "{$rg}";
294
				add_hostname_to_watch($rg);
295
				if (!platform_booting()) {
296
					$rg = resolve_retry($rg);
297
				}
298
				if (!is_ipaddr($rg)) {
299
					continue;
300
				}
301
			}
302
			if (array_search($rg, $rgmap)) {
303
				log_error(sprintf(gettext("The remote gateway %s already exists on another phase 1 entry"), $rg));
304
				continue;
305
			}
306
			$rgmap[$ph1ent['remote-gateway']] = $rg;
307

    
308
			if (is_array($a_phase2)) {
309
				/* step through each phase2 entry */
310
				foreach ($a_phase2 as $ph2ent) {
311
					if (isset($ph2ent['disabled'])) {
312
						continue;
313
					}
314

    
315
					if ($ikeid != $ph2ent['ikeid']) {
316
						continue;
317
					}
318

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

    
378
	$accept_unencrypted = "";
379
	if (isset($config['ipsec']['acceptunencryptedmainmode'])) {
380
		$accept_unencrypted = "accept_unencrypted_mainmode_messages = yes";
381
	}
382

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

    
388
	$i_dont_care_about_security_and_use_aggressive_mode_psk = "";
389
	if ($aggressive_mode_psk) {
390
		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.");
391
		if (!empty($stronconf) && strpos($stronconf, 'i_dont_care_about_security_and_use_aggressive_mode_psk') === FALSE) {
392
			$restart = true;
393
		}
394
		$i_dont_care_about_security_and_use_aggressive_mode_psk = "i_dont_care_about_security_and_use_aggressive_mode_psk=yes";
395
	}
396

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

    
399
	$makebeforebreak = '';
400
	if (isset($config['ipsec']['makebeforebreak'])) {
401
		$makebeforebreak = 'make_before_break = yes';
402
	}
403

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

    
414
	unset($stronconf);
415

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

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

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

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

    
459
	plugins {
460
		# Load defaults
461
		include {$g['varetc_path']}/ipsec/strongswan.d/charon/*.conf
462

    
463
		stroke {
464
			secrets_file = {$g['varetc_path']}/ipsec/ipsec.secrets
465
		}
466

    
467
		unity {
468
			load = {$unity_enabled}
469
		}
470

    
471
EOD;
472

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

    
488
EOD;
489
		}
490
	}
491

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

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

    
510
EOD;
511
	}
512

    
513
	if (is_array($a_client) && isset($a_client['enable'])) {
514
		$strongswan .= "\t\tattr {\n";
515

    
516
		$cfgservers = array();
517
		if (!empty($a_client['dns_server1'])) {
518
			$cfgservers[] = $a_client['dns_server1'];
519
		}
520
		if (!empty($a_client['dns_server2'])) {
521
			$cfgservers[] = $a_client['dns_server2'];
522
		}
523
		if (!empty($a_client['dns_server3'])) {
524
			$cfgservers[] = $a_client['dns_server3'];
525
		}
526
		if (!empty($a_client['dns_server4'])) {
527
			$cfgservers[] = $a_client['dns_server4'];
528
		}
529

    
530
		if (!empty($cfgservers)) {
531
			$strongswan .= "\t\t\tdns = " . implode(",", $cfgservers) . "\n";
532
		}
533
		unset($cfgservers);
534
		$cfgservers = array();
535
		if (!empty($a_client['wins_server1'])) {
536
			$cfgservers[] = $a_client['wins_server1'];
537
		}
538
		if (!empty($a_client['wins_server2'])) {
539
			$cfgservers[] = $a_client['wins_server2'];
540
		}
541
		if (!empty($cfgservers)) {
542
			$strongswan .= "\t\t\tnbns = " . implode(",", $cfgservers) . "\n";
543
		}
544
		unset($cfgservers);
545

    
546
		if (isset($a_client['net_list']) && is_array($a_phase2)) {
547
			$net_list = '';
548
			foreach ($a_phase2 as $ph2ent) {
549
				if (isset($ph2ent['disabled'])) {
550
					continue;
551
				}
552

    
553
				if (!isset($ph2ent['mobile'])) {
554
					continue;
555
				}
556

    
557
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
558

    
559
				if (!empty($net_list)) {
560
					$net_list .= ",";
561
				}
562
				$net_list .= $localid;
563
			}
564

    
565
			if (!empty($net_list)) {
566
				$strongswan .= "\t\t\tsubnet = {$net_list}\n";
567
				$strongswan .= "\t\t\tsplit-include = {$net_list}\n";
568
				unset($net_list);
569
			}
570
		}
571

    
572
		if (!empty($a_client['dns_domain'])) {
573
			$strongswan .= "\t\t\t# Search domain and default domain\n";
574
			$strongswan .= "\t\t\t28674 = \"{$a_client['dns_domain']}\"\n";
575
			if (empty($a_client['dns_split'])) {
576
				$strongswan .= "\t\t\t28675 = \"{$a_client['dns_domain']}\"";
577
			}
578
			$strongswan .= "\n";
579
		}
580

    
581
		if (!empty($a_client['dns_split'])) {
582
			$strongswan .= "\t\t\t28675 = {$a_client['dns_split']}\n";
583
		}
584

    
585
		if (!empty($a_client['login_banner'])) {
586
			$strongswan .= "\t\t\t28672 = \"{$a_client['login_banner']}\"\n";
587
		}
588

    
589
		if (isset($a_client['save_passwd'])) {
590
			$strongswan .= "\t\t\t28673 = 1\n";
591
		}
592

    
593
		if ($a_client['pfs_group']) {
594
			$strongswan .= "\t\t\t28679 = \"{$a_client['pfs_group']}\"\n";
595
		}
596
		$strongswan .= "\t\t}\n";
597

    
598
		if ($a_client['user_source'] != "none") {
599
			$strongswan .= "\t\txauth-generic {\n";
600
			$strongswan .= "\t\t\tscript = /etc/inc/ipsec.auth-user.php\n";
601
			$strongswan .= "\t\t\tauthcfg = ";
602
			$firstsed = 0;
603
			$authcfgs = explode(",", $a_client['user_source']);
604
			foreach ($authcfgs as $authcfg) {
605
				if ($firstsed > 0) {
606
					$strongswan .= ",";
607
				}
608
				if ($authcfg == "system") {
609
					$authcfg = "Local Database";
610
				}
611
				$strongswan .= $authcfg;
612
				$firstsed = 1;
613
			}
614
			$strongswan .= "\n";
615
			$strongswan .= "\t\t}\n";
616
		}
617
	}
618

    
619
	$strongswan .= "\n\t}\n}\n";
620
	@file_put_contents("{$g['varetc_path']}/ipsec/strongswan.conf", $strongswan);
621
	unset($strongswan);
622

    
623
	/* write out CRL files */
624
	if (is_array($config['crl']) && count($config['crl'])) {
625
		foreach ($config['crl'] as $crl) {
626
			if (!isset($crl['text'])) {
627
				log_error(sprintf(gettext("Warning: Missing CRL data for %s"), $crl['descr']));
628
				continue;
629
			}
630
			$fpath = "{$crlpath}/{$crl['refid']}.crl";
631
			if (!@file_put_contents($fpath, base64_decode($crl['text']))) {
632
				log_error(sprintf(gettext("Error: Cannot write IPsec CRL file for %s"), $crl['descr']));
633
				continue;
634
			}
635
		}
636
	}
637

    
638
	$pskconf = "";
639

    
640
	$vpncas = array();
641
	if (is_array($a_phase1) && count($a_phase1)) {
642
		foreach ($a_phase1 as $ph1ent) {
643

    
644
			if (isset($ph1ent['disabled'])) {
645
				continue;
646
			}
647

    
648
			if (strstr($ph1ent['authentication_method'], 'rsa') ||
649
			    in_array($ph1ent['authentication_method'], array('eap-mschapv2', 'eap-tls', 'eap-radius'))) {
650
				$certline = '';
651

    
652
				$ikeid = $ph1ent['ikeid'];
653
				$cert = lookup_cert($ph1ent['certref']);
654

    
655
				if (!$cert) {
656
					log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
657
					continue;
658
				}
659

    
660
				/* add signing CA cert chain of server cert
661
				 * to the list of CAs to write
662
				 */
663
				$cachain = ca_chain_array($cert);
664
				if ($cachain && is_array($cachain)) {
665
					foreach ($cachain as $cacrt) {
666
						$vpncas[$cacrt['refid']] = $cacrt;
667
					}
668
				}
669

    
670
				@chmod($certpath, 0600);
671

    
672
				$ph1keyfile = "{$keypath}/cert-{$ikeid}.key";
673
				if (!file_put_contents($ph1keyfile, base64_decode($cert['prv']))) {
674
					log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
675
					continue;
676
				}
677
				@chmod($ph1keyfile, 0600);
678

    
679
				$ph1certfile = "{$certpath}/cert-{$ikeid}.crt";
680
				if (!file_put_contents($ph1certfile, base64_decode($cert['crt']))) {
681
					log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
682
					@unlink($ph1keyfile);
683
					continue;
684
				}
685
				@chmod($ph1certfile, 0600);
686

    
687
				/* XXX" Traffic selectors? */
688
				$pskconf .= " : RSA {$ph1keyfile}\n";
689
			} else {
690
				list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local');
691
				list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap);
692

    
693
				$myid = trim($myid_data);
694

    
695
				if (empty($peerid_data)) {
696
					continue;
697
				}
698

    
699
				if ($myid_type == 'fqdn' && !empty($myid)) {
700
					$myid = "@{$myid}";
701
				}
702

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

    
705
				$peerid = ($peerid_data != 'allusers') ? trim($peerid_data) : '';
706

    
707
				if ($peerid_type == 'fqdn' && !empty($peerid)) {
708
					$peerid = "@{$peerid}";
709
				}
710

    
711
				if (!empty($ph1ent['pre-shared-key'])) {
712
					$pskconf .= "{$myid} {$peerid} : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n";
713
					if (isset($ph1ent['mobile'])) {
714
						$pskconf .= " : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n";
715
					}
716
				}
717
			}
718

    
719
			/* if the client authenticates with a cert add the
720
			 * client cert CA chain to the list of CAs to write
721
			 */
722
			if (in_array($ph1ent['authentication_method'],
723
			array('rsasig', 'eap-tls', 'xauth_rsa_server'))) {
724

    
725
				if (!empty($ph1ent['caref']) && !array_key_exists($ph1ent['caref'], $vpncas)) {
726
					$thisca = lookup_ca($ph1ent['caref']);
727
					$vpncas[$ph1ent['caref']] = $thisca;
728

    
729
					/* follow chain up to root */
730
					$cachain = ca_chain_array($thisca);
731
					if ($cachain and is_array($cachain)) {
732
						foreach ($cachain as $cacrt) {
733
							$vpncas[$cacrt['refid']] = $cacrt;
734
						}
735
					}
736
				}
737
			}
738
		}
739
	}
740

    
741
	/* write the required CAs */
742
	foreach ($vpncas as $carefid => $cadata) {
743
		$cacrt = base64_decode($cadata['crt']);
744
		$cacrtattrs = openssl_x509_parse($cacrt);
745
		if (!is_array($cacrtattrs) || !isset($cacrtattrs['hash'])) {
746
			log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $cadata['descr']));
747
			continue;
748
		}
749
		$cafilename = "{$capath}/{$cacrtattrs['hash']}.0.crt";
750
		if (!@file_put_contents($cafilename, $cacrt)) {
751
				log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $cadata['descr']));
752
				continue;
753
		}
754
	}
755

    
756
	/* Add user PSKs */
757
	if (is_array($config['system']) && is_array($config['system']['user'])) {
758
		foreach ($config['system']['user'] as $user) {
759
			if (!empty($user['ipsecpsk'])) {
760
				$pskconf .= "{$myid} {$user['name']} : PSK 0s" . base64_encode($user['ipsecpsk']) . "\n";
761
			}
762
		}
763
		unset($user);
764
	}
765

    
766
	/* add PSKs for mobile clients */
767
	if (is_array($ipseccfg['mobilekey'])) {
768
		foreach ($ipseccfg['mobilekey'] as $key) {
769
			if ($key['ident'] == "allusers") {
770
				$key['ident'] = '%any';
771
			}
772
			if ($key['ident'] == "any") {
773
				$key['ident'] = '%any';
774
			}
775
			if (empty($key['type'])) {
776
				$key['type'] = 'PSK';
777
			}
778
			$pskconf .= " {$key['ident']} : {$key['type']} 0s" . base64_encode($key['pre-shared-key']) . "\n";
779
		}
780
		unset($key);
781
	}
782

    
783
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.secrets", $pskconf);
784
	chmod("{$g['varetc_path']}/ipsec/ipsec.secrets", 0600);
785
	unset($pskconf);
786

    
787
	$uniqueids = 'yes';
788
	if (!empty($config['ipsec']['uniqueids'])) {
789
		if (array_key_exists($config['ipsec']['uniqueids'], $ipsec_idhandling)) {
790
			$uniqueids = $config['ipsec']['uniqueids'];
791
		}
792
	}
793
	$natfilterrules = false;
794
	/* begin ipsec.conf */
795
	$ipsecconf = "";
796
	$enablecompression = false;
797
	if (is_array($a_phase1) && count($a_phase1)) {
798

    
799
		$ipsecconf .= "# This file is automatically generated. Do not edit\n";
800
		$ipsecconf .= "config setup\n\tuniqueids = {$uniqueids}\n";
801

    
802
		if (isset($config['ipsec']['strictcrlpolicy'])) {
803
			$ipsecconf .= "\tstrictcrlpolicy = yes \n";
804
		}
805

    
806
		if (!isset($config['ipsec']['noshuntlaninterfaces'])) {
807
			if ($config['interfaces']['lan']) {
808
				$lanip = get_interface_ip("lan");
809
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
810
					$lansn = get_interface_subnet("lan");
811
					$lansa = gen_subnet($lanip, $lansn);
812
					if (!empty($lansa) && !empty($lansn)) {
813
						$ipsecconf .= <<<EOD
814

    
815
conn bypasslan
816
	leftsubnet = {$lansa}/{$lansn}
817
	rightsubnet = {$lansa}/{$lansn}
818
	authby = never
819
	type = passthrough
820
	auto = route
821

    
822
EOD;
823
					}
824
				}
825
			}
826
		}
827

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

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

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

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

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

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

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

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

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

    
956
			if (is_array($ph1ent['encryption-algorithm']) && !empty($ph1ent['encryption-algorithm']['name']) && !empty($ph1ent['hash-algorithm'])) {
957
				$ealgosp1 = '';
958
				$ealg_id = $ph1ent['encryption-algorithm']['name'];
959
				$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
960
				if ($ealg_kl) {
961
					$ealgosp1 = "ike = {$ealg_id}{$ealg_kl}-{$ph1ent['hash-algorithm']}";
962
				} else {
963
					$ealgosp1 = "ike = {$ealg_id}-{$ph1ent['hash-algorithm']}";
964
				}
965

    
966
				$modp = vpn_ipsec_convert_to_modp($ph1ent['dhgroup']);
967
				if (!empty($modp)) {
968
					$ealgosp1 .= "-{$modp}";
969
				}
970

    
971
				$ealgosp1 .= "!";
972
			}
973

    
974
			if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
975
				if ($passive == "route") {
976
					$dpdline = "dpdaction = restart";
977
				} else {
978
					$dpdline = "dpdaction = clear";
979
				}
980
				$dpdline .= "\n\tdpddelay = {$ph1ent['dpd_delay']}s";
981
				$dpdtimeout = $ph1ent['dpd_delay'] * ($ph1ent['dpd_maxfail'] + 1);
982
				$dpdline .= "\n\tdpdtimeout = {$dpdtimeout}s";
983
			} else {
984
				$dpdline = "dpdaction = none";
985
			}
986

    
987
			$ikelifeline = '';
988
			if ($ph1ent['lifetime']) {
989
				$ikelifeline = "ikelifetime = {$ph1ent['lifetime']}s";
990
			}
991

    
992
			$rightsourceip = NULL;
993
			if (isset($ph1ent['mobile'])) {
994
				$rightsourceips = array();
995
				if (!empty($a_client['pool_address'])) {
996
					$rightsourceips[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
997
				}
998
				if (!empty($a_client['pool_address_v6'])) {
999
					$rightsourceips[] = "{$a_client['pool_address_v6']}/{$a_client['pool_netbits_v6']}";
1000
				}
1001
				if ($ph1ent['authentication_method'] == "eap-radius" && !count($rightsourceips)) {
1002
					$rightsourceips[] = "%radius";
1003
				}
1004
				if (count($rightsourceips)) {
1005
					$rightsourceip = "\trightsourceip = " . implode(',', $rightsourceips) . "\n";
1006
				}
1007
			}
1008

    
1009
			if (!empty($ph1ent['caref'])) {
1010
				$ca = lookup_ca($ph1ent['caref']);
1011
				if ($ca) {
1012
					$casubarr = cert_get_subject_array($ca['crt']);
1013
					$casub = "";
1014
					foreach ($casubarr as $casubfield) {
1015
						if (empty($casub)) {
1016
							$casub = "/";
1017
						}
1018
						/* The subfield value could be an array. To avoid duplicating code,
1019
						 * always make it an array then iterate.
1020
						 * See https://redmine.pfsense.org/issues/7929
1021
						 */
1022
						if (!is_array($casubfield['v'])) {
1023
							$casubfield['v'] = array($casubfield['v']);
1024
						}
1025
						foreach ($casubfield['v'] as $casubval) {
1026
							$casub .= "{$casubfield['a']}={$casubval}/";
1027
						}
1028
					}
1029

    
1030
				}
1031
			}
1032

    
1033
			$authentication = "";
1034
			switch ($ph1ent['authentication_method']) {
1035
				case 'eap-mschapv2':
1036
					if (isset($ph1ent['mobile'])) {
1037
						$authentication = "eap_identity=%any\n\t";
1038
						$authentication .= "leftauth=pubkey\n\trightauth=eap-mschapv2";
1039
						if (!empty($ph1ent['certref'])) {
1040
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1041
							$authentication .= "\n\tleftsendcert=always";
1042
						}
1043
					}
1044
					break;
1045
				case 'eap-tls':
1046
					if (isset($ph1ent['mobile'])) {
1047
						$authentication = "eap_identity=%identity\n\t";
1048
						$authentication .= "leftauth=pubkey\n\trightauth=eap-tls";
1049
						if (!empty($ph1ent['certref'])) {
1050
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1051
							$authentication .= "\n\tleftsendcert=always";
1052
						}
1053
					} else {
1054
						$authentication = "leftauth=eap-tls\n\trightauth=eap-tls";
1055
						if (!empty($ph1ent['certref'])) {
1056
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1057
							$authentication .= "\n\tleftsendcert=always";
1058
						}
1059
					}
1060
					if (isset($casub)) {
1061
						$authentication .= "\n\trightca=\"$casub\"";
1062
					}
1063
					break;
1064
				case 'eap-radius':
1065
					if (isset($ph1ent['mobile'])) {
1066
						$authentication = "eap_identity=%identity\n\t";
1067
						$authentication .= "leftauth=pubkey\n\trightauth=eap-radius";
1068
						if (!empty($ph1ent['certref'])) {
1069
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1070
							$authentication .= "\n\tleftsendcert=always";
1071
						}
1072
					} else {
1073
						$authentication = "leftauth=eap-radius\n\trightauth=eap-radius";
1074
						if (!empty($ph1ent['certref'])) {
1075
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1076
							$authentication .= "\n\tleftsendcert=always";
1077
						}
1078
					}
1079
					break;
1080
				case 'xauth_rsa_server':
1081
					$authentication = "leftauth = pubkey\n\trightauth = pubkey";
1082
					$authentication .= "\n\trightauth2 = xauth-generic";
1083
					if (!empty($ph1ent['certref'])) {
1084
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1085
						$authentication .= "\n\tleftsendcert=always";
1086
					}
1087
					if (isset($casub)) {
1088
						$authentication .= "\n\trightca=\"$casub\"";
1089
					}
1090
					break;
1091
				case 'xauth_psk_server':
1092
					$authentication = "leftauth = psk\n\trightauth = psk";
1093
					$authentication .= "\n\trightauth2 = xauth-generic";
1094
					break;
1095
				case 'pre_shared_key':
1096
					$authentication = "leftauth = psk\n\trightauth = psk";
1097
					break;
1098
				case 'rsasig':
1099
					$authentication = "leftauth = pubkey\n\trightauth = pubkey";
1100
					if (!empty($ph1ent['certref'])) {
1101
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1102
						$authentication .= "\n\tleftsendcert=always";
1103
					}
1104
					if (isset($casub)) {
1105
						$authentication .= "\n\trightca=\"$casub\"";
1106
					}
1107
					break;
1108
				case 'hybrid_rsa_server':
1109
					$authentication = "leftauth = pubkey\n\trightauth = xauth-generic";
1110
					if (!empty($ph1ent['certref'])) {
1111
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1112
						$authentication .= "\n\tleftsendcert=always";
1113
					}
1114
					break;
1115
			}
1116

    
1117
			$left_spec = $ep;
1118

    
1119
			if (isset($ph1ent['reauth_enable'])) {
1120
				$reauth = "reauth = no";
1121
			} else {
1122
				$reauth = "reauth = yes";
1123
			}
1124

    
1125
			if (isset($ph1ent['rekey_enable'])) {
1126
				$rekeyline = "rekey = no";
1127
			} else {
1128
				$rekeyline = "rekey = yes";
1129
				if(!empty($ph1ent['margintime'])){
1130
					$rekeyline .= "\n\tmargintime = {$ph1ent['margintime']}s";
1131
				}
1132
			}
1133

    
1134
			if ($ph1ent['nat_traversal'] == 'off') {
1135
				$forceencaps = 'forceencaps = no';
1136
			} else if ($ph1ent['nat_traversal'] == 'force') {
1137
				$forceencaps = 'forceencaps = yes';
1138
			} else {
1139
				$forceencaps = 'forceencaps = no';
1140
			}
1141

    
1142
			if ($ph1ent['mobike'] == 'on') {
1143
				$mobike = 'mobike = yes';
1144
			} else {
1145
				$mobike = 'mobike = no';
1146
			}
1147

    
1148
			if (isset($ph1ent['tfc_enable'])) {
1149
				if (isset($ph1ent['tfc_bytes']) && is_numericint($ph1ent['tfc_bytes'])) {
1150
					$tfc = "tfc = {$ph1ent['tfc_bytes']}";
1151
				} else {
1152
					$tfc = "tfc = %mtu";
1153
				}
1154
			}
1155

    
1156
			$ipseclifetime = 0;
1157
			$rightsubnet_spec = array();
1158
			$leftsubnet_spec = array();
1159
			$reqids = array();
1160
			$ealgoAHsp2arr = array();
1161
			$ealgoESPsp2arr = array();
1162
			if (is_array($a_phase2) && count($a_phase2)) {
1163
				foreach ($a_phase2 as $ph2ent) {
1164
					if ($ikeid != $ph2ent['ikeid']) {
1165
						continue;
1166
					}
1167

    
1168
					if (isset($ph2ent['disabled'])) {
1169
						continue;
1170
					}
1171

    
1172
					if (isset($ph2ent['mobile']) && !isset($a_client['enable'])) {
1173
						continue;
1174
					}
1175

    
1176
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
1177
						$tunneltype = "type = tunnel";
1178

    
1179
						$localid_type = $ph2ent['localid']['type'];
1180
						$leftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']);
1181

    
1182
						/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
1183
						if (($localid_type == "none" || $localid_type == "mobile") &&
1184
						    isset($ph1ent['mobile']) && (ipsec_get_number_of_phase2($ikeid) == 1)) {
1185
							$left_spec = '%any';
1186
						} else {
1187
							if ($localid_type != "address") {
1188
								$localid_type = "subnet";
1189
							}
1190
							// Don't let an empty subnet into config, it can cause parse errors. Ticket #2201.
1191
							if (!is_ipaddr($leftsubnet_data) && !is_subnet($leftsubnet_data) && ($leftsubnet_data != "0.0.0.0/0")) {
1192
								log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet.");
1193
								continue;
1194
							}
1195
							if (!empty($ph2ent['natlocalid'])) {
1196
								$natleftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], false, $ph2ent['mode']);
1197
								if ($ph2ent['natlocalid']['type'] != "address") {
1198
									if (is_subnet($natleftsubnet_data)) {
1199
										$leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}";
1200
									}
1201
								} else {
1202
									if (is_ipaddr($natleftsubnet_data)) {
1203
										$leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}";
1204
									}
1205
								}
1206
								$natfilterrules = true;
1207
							}
1208
						}
1209

    
1210
						$leftsubnet_spec[] = $leftsubnet_data;
1211

    
1212
						if (!isset($ph2ent['mobile'])) {
1213
							$tmpsubnet = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
1214
							$rightsubnet_spec[] = $tmpsubnet;
1215
						} else if (!empty($a_client['pool_address'])) {
1216
							$rightsubnet_spec[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
1217
						}
1218
					} else {
1219
						$tunneltype = "type = transport";
1220

    
1221
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
1222
						    ($ph1ent['authentication_method'] == "pre_shared_key")) &&
1223
						    isset($ph1ent['mobile'])) {
1224
							$left_spec = "%any";
1225
						} else {
1226
							$tmpsubnet = ipsec_get_phase1_src($ph1ent);
1227
							$leftsubnet_spec[] = $tmpsubnet;
1228
						}
1229

    
1230
						if (!isset($ph2ent['mobile'])) {
1231
							$rightsubnet_spec[] = $right_spec;
1232
						}
1233
					}
1234

    
1235
					if (isset($a_client['pfs_group']) && isset($ph2ent['mobile'])) {
1236
						$ph2ent['pfsgroup'] = $a_client['pfs_group'];
1237
					}
1238

    
1239
					if ($ph2ent['protocol'] == 'esp') {
1240
						if (is_array($ph2ent['encryption-algorithm-option'])) {
1241
							foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
1242
								$ealg_id = $ealg['name'];
1243
								$ealg_kl = $ealg['keylen'];
1244

    
1245
								if (!empty($ealg_kl) && $ealg_kl == "auto") {
1246
									if (empty($p2_ealgos) || !is_array($p2_ealgos)) {
1247
										require_once("ipsec.inc");
1248
									}
1249
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
1250
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
1251
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
1252
									/* XXX: in some cases where include ordering is suspect these variables
1253
									 * are somehow 0 and we enter this loop forever and timeout after 900
1254
									 * seconds wrecking bootup */
1255
									if ($key_hi != 0 and $key_lo != 0 and $key_step != 0) {
1256
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
1257
											if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1258
												foreach ($ph2ent['hash-algorithm-option'] as $halgo) {
1259
													$halgo = str_replace('hmac_', '', $halgo);
1260
													$tmpealgo = "{$ealg_id}{$keylen}-{$halgo}";
1261
													$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1262
													if (!empty($modp)) {
1263
														$tmpealgo .= "-{$modp}";
1264
													}
1265
													$ealgoESPsp2arr[] = $tmpealgo;
1266
												}
1267
											} else {
1268
												$tmpealgo = "{$ealg_id}{$keylen}";
1269
												$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1270
												if (!empty($modp)) {
1271
													$tmpealgo .= "-{$modp}";
1272
												}
1273
												$ealgoESPsp2arr[] = $tmpealgo;
1274
											}
1275
										}
1276
									}
1277
								} else {
1278
									if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1279
										foreach ($ph2ent['hash-algorithm-option'] as $halgo) {
1280
											$halgo = str_replace('hmac_', '', $halgo);
1281
											$tmpealgo = "{$ealg_id}{$ealg_kl}-{$halgo}";
1282
											$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1283
											if (!empty($modp)) {
1284
												$tmpealgo .= "-{$modp}";
1285
											}
1286
											$ealgoESPsp2arr[] = $tmpealgo;
1287
										}
1288
									} else {
1289
										$tmpealgo = "{$ealg_id}{$ealg_kl}";
1290
										$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1291
										if (!empty($modp)) {
1292
											$tmpealgo .= "-{$modp}";
1293
										}
1294
										$ealgoESPsp2arr[] = $tmpealgo;
1295
									}
1296
								}
1297
							}
1298
						}
1299
					} else if ($ph2ent['protocol'] == 'ah') {
1300
						if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1301
							$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1302
							foreach ($ph2ent['hash-algorithm-option'] as $tmpAHalgo) {
1303
								$tmpAHalgo = str_replace('hmac_', '', $tmpAHalgo);
1304
								if (!empty($modp)) {
1305
									$tmpAHalgo = "-{$modp}";
1306
								}
1307
								$ealgoAHsp2arr[] = $tmpAHalgo;
1308
							}
1309
						}
1310
					}
1311

    
1312
					$reqids[] = $ph2ent['reqid'];
1313

    
1314
					if (!empty($ph2ent['lifetime'])) {
1315
						if ($ipseclifetime == 0 || intval($ipseclifetime) > intval($ph2ent['lifetime'])) {
1316
							$ipseclifetime = intval($ph2ent['lifetime']);
1317
						}
1318
					}
1319

    
1320
				}
1321
			}
1322

    
1323
			$ipsecconnect =<<<EOD
1324
	fragmentation = yes
1325
	keyexchange = {$keyexchange}
1326
	{$reauth}
1327
	{$forceencaps}
1328
	{$mobike}
1329
	{$tfc}
1330
	{$rekeyline}
1331
	installpolicy = yes
1332
	{$tunneltype}
1333
	{$dpdline}
1334
	auto = {$passive}
1335
	left = {$left_spec}
1336
	right = {$right_spec}
1337
	{$leftid}
1338

    
1339
EOD;
1340

    
1341
			/* Disable ipcomp for now. redmine #6167
1342
			if (isset($config['ipsec']['compression'])) {
1343
				$ipsecconnect .= "\tcompress = yes\n";
1344
				$enablecompression = true;
1345
			} */
1346
			if (!empty($ikelifeline)) {
1347
				$ipsecconnect .= "\t{$ikelifeline}\n";
1348
			}
1349
			if ($ipseclifetime > 0) {
1350
				$ipsecconnect .= "\tlifetime = {$ipseclifetime}s\n";
1351
			}
1352
			if (!empty($rightsourceip)) {
1353
				$ipsecconnect .= "{$rightsourceip}";
1354
			}
1355
			if (!empty($ealgosp1)) {
1356
				$ipsecconnect .= "\t{$ealgosp1}\n";
1357
			}
1358
			if (!empty($ealgoAHsp2arr)) {
1359
				$ipsecconnect .= "\tah = " . join(',', $ealgoAHsp2arr) . "!\n";
1360
			}
1361
			if (!empty($ealgoESPsp2arr)) {
1362
				$ipsecconnect .= "\tesp = " . join(',', $ealgoESPsp2arr) . "!\n";
1363
			}
1364
			if (!empty($authentication)) {
1365
				$ipsecconnect .= "\t{$authentication}\n";
1366
			}
1367
			if (!empty($peerid_spec)) {
1368
				$ipsecconnect .= "\trightid = {$peerid_spec}\n";
1369
			}
1370
			if ($keyexchange != 'ikev2') {
1371
				$ipsecconnect .= "\taggressive = {$aggressive}\n";
1372
			}
1373

    
1374
			if (!isset($ph1ent['mobile']) && ($keyexchange == 'ikev1' || isset($ph1ent['splitconn']))) {
1375
				if (!empty($rightsubnet_spec)) {
1376
					$ipsecfin = '';
1377
					foreach ($rightsubnet_spec as $idx => $rsubnet) {
1378
						$ipsecfin .= "\nconn con{$ph1ent['ikeid']}00{$idx}\n";
1379
						//if (!empty($reqids[$idx])) {
1380
						//	$ipsecfin .= "\treqid = " . $reqids[$idx] . "\n";
1381
						//}
1382
						$ipsecfin .= $ipsecconnect;
1383
						$ipsecfin .= "\trightsubnet = {$rsubnet}\n";
1384
						$ipsecfin .= "\tleftsubnet = " . $leftsubnet_spec[$idx] . "\n";
1385
					}
1386
				} else {
1387
					log_error(sprintf(gettext("No phase2 specifications for tunnel with REQID = %s"), $ikeid));
1388
				}
1389
			} else {
1390
				$ipsecfin = "\nconn con{$ph1ent['ikeid']}\n";
1391
				//if (!empty($reqids[$idx])) {
1392
				//	$ipsecfin .= "\treqid = " . $reqids[0] . "\n";
1393
				//}
1394
				$ipsecfin .= $ipsecconnect;
1395
				if (!isset($ph1ent['mobile']) && !empty($rightsubnet_spec)) {
1396
					$tempsubnets = array();
1397
					foreach ($rightsubnet_spec as $rightsubnet) {
1398
						$tempsubnets[$rightsubnet] = $rightsubnet;
1399
					}
1400
					$ipsecfin .= "\trightsubnet = " . join(",", $tempsubnets) . "\n";
1401
					unset($tempsubnets, $rightsubnet);
1402
				}
1403
				if (!empty($leftsubnet_spec)) {
1404
					$tempsubnets = array();
1405
					foreach ($leftsubnet_spec as $leftsubnet) {
1406
						$tempsubnets[$leftsubnet] = $leftsubnet;
1407
					}
1408
					$ipsecfin .= "\tleftsubnet = " . join(",", $tempsubnets) . "\n";
1409
					unset($tempsubnets, $leftsubnet);
1410
				}
1411
			}
1412
			$ipsecconf .= $ipsecfin;
1413
			unset($ipsecfin);
1414
		}
1415
	}
1416

    
1417
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.conf", $ipsecconf);
1418
	unset($ipsecconf);
1419
	/* end ipsec.conf */
1420

    
1421
	if ($enablecompression === true) {
1422
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 1);
1423
	} else {
1424
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 0);
1425
	}
1426

    
1427
	/* manage process */
1428
	if ($restart === true) {
1429
		mwexec("/usr/local/sbin/ipsec restart", false);
1430
	} else {
1431
		if (isvalidpid("{$g['varrun_path']}/starter.charon.pid")) {
1432
			/* Update configuration changes */
1433
			/* Read secrets */
1434
			mwexec("/usr/local/sbin/ipsec rereadall", false);
1435
			mwexec("/usr/local/sbin/ipsec reload", false);
1436
		} else {
1437
			mwexec("/usr/local/sbin/ipsec start", false);
1438
		}
1439
	}
1440

    
1441
	// run ping_hosts.sh once if it's enabled to avoid wait for minicron
1442
	if ($ipsecpinghostsactive == true) {
1443
		mwexec_bg("/usr/local/bin/ping_hosts.sh");
1444
	}
1445

    
1446
	if ($natfilterrules == true) {
1447
		filter_configure();
1448
	}
1449
	/* start filterdns, if necessary */
1450
	if (count($filterdns_list) > 0) {
1451
		$interval = 60;
1452
		if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval'])) {
1453
			$interval = $ipseccfg['dns-interval'];
1454
		}
1455

    
1456
		$hostnames = "";
1457
		array_unique($filterdns_list);
1458
		foreach ($filterdns_list as $hostname) {
1459
			$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
1460
		}
1461
		file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
1462
		unset($hostnames);
1463

    
1464
		if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid")) {
1465
			sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
1466
		} else {
1467
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
1468
		}
1469
	} else {
1470
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
1471
		@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
1472
	}
1473

    
1474
	if (platform_booting()) {
1475
		echo "done\n";
1476
	}
1477

    
1478
	unlock($ipsecstartlock);
1479
	return count($filterdns_list);
1480
}
1481

    
1482
/*
1483
 * Forcefully restart IPsec
1484
 * This is required for when dynamic interfaces reload
1485
 * For all other occasions the normal vpn_ipsec_configure()
1486
 * will gracefully reload the settings without restarting
1487
 */
1488
function vpn_ipsec_force_reload($interface = "") {
1489
	global $g, $config;
1490

    
1491
	if (!ipsec_enabled()) {
1492
		return;
1493
	}
1494

    
1495
	$ipseccfg = $config['ipsec'];
1496

    
1497
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1498
		$found = false;
1499
		foreach ($ipseccfg['phase1'] as $ipsec) {
1500
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1501
				$found = true;
1502
				break;
1503
			}
1504
		}
1505
		if (!$found) {
1506
			log_error(sprintf(gettext("Ignoring IPsec reload since there are no tunnels on interface %s"), $interface));
1507
			return;
1508
		}
1509
	}
1510

    
1511
	/* If we get this far then we need to take action. */
1512
	log_error(gettext("Forcefully reloading IPsec"));
1513
	vpn_ipsec_configure();
1514
}
1515

    
1516
/* master setup for vpn (mpd) */
1517
function vpn_setup() {
1518
	/* start pppoe server */
1519
	vpn_pppoes_configure();
1520

    
1521
	/* setup l2tp */
1522
	vpn_l2tp_configure();
1523
}
1524

    
1525
function vpn_netgraph_support() {
1526
	$iflist = get_configured_interface_list();
1527
	foreach ($iflist as $iface) {
1528
		$realif = get_real_interface($iface);
1529
		/* Get support for netgraph(4) from the nic */
1530
		$ifinfo = pfSense_get_interface_addresses($realif);
1531
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge"))) {
1532
			pfSense_ngctl_attach(".", $realif);
1533
		}
1534
	}
1535
}
1536

    
1537
function vpn_pppoes_configure() {
1538
	global $config;
1539

    
1540
	if (is_array($config['pppoes']['pppoe'])) {
1541
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
1542
			vpn_pppoe_configure($pppoe);
1543
		}
1544
	}
1545
}
1546

    
1547
function vpn_pppoe_configure(&$pppoecfg) {
1548
	global $config, $g;
1549

    
1550
	$syscfg = $config['system'];
1551

    
1552
	/* create directory if it does not exist */
1553
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
1554
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1555
	}
1556

    
1557
	if (platform_booting()) {
1558
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
1559
			return 0;
1560
		}
1561

    
1562
		echo gettext("Configuring PPPoE Server service... ");
1563
	} else {
1564
		/* kill mpd */
1565
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1566

    
1567
		/* wait for process to die */
1568
		sleep(2);
1569

    
1570
	}
1571

    
1572
	switch ($pppoecfg['mode']) {
1573

    
1574
		case 'server':
1575

    
1576
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1577

    
1578
			if ($pppoecfg['paporchap'] == "chap") {
1579
				$paporchap = "set link enable chap";
1580
			} else {
1581
				$paporchap = "set link enable pap";
1582
			}
1583

    
1584
			/* write mpd.conf */
1585
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1586
			if (!$fd) {
1587
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1588
				return 1;
1589
			}
1590

    
1591
			$issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 ";
1592
			if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1593
				$issue_ip_type .= "0.0.0.0/0";
1594
			} else {
1595
				$issue_ip_type .= "ippool p0";
1596
			}
1597

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

    
1600
			if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
1601
				$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
1602
			} else {
1603
				$pppoemaxlogins = 1;
1604
			}
1605

    
1606
			$ipcp_dns = '';
1607
			if (!empty($pppoecfg['dns1'])) {
1608
				$ipcp_dns = "set ipcp dns " . $pppoecfg['dns1'];
1609
				if (!empty($pppoecfg['dns2'])) {
1610
					$ipcp_dns .= " " . $pppoecfg['dns2'];
1611
				}
1612
			} elseif (isset($config['dnsmasq']['enable']) ||
1613
			    isset ($config['unbound']['enable'])) {
1614
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1615
				if ($syscfg['dnsserver'][0]) {
1616
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1617
				}
1618
			} elseif (is_array($syscfg['dnsserver']) &&
1619
			    ($syscfg['dnsserver'][0])) {
1620
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1621
			}
1622

    
1623
			$mpdconf = <<<EOD
1624
startup:
1625

    
1626
poes:
1627
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
1628

    
1629
	create bundle template poes_b
1630
	set bundle enable compression
1631

    
1632
	set ccp yes mppc
1633
	set mppc yes e40
1634
	set mppc yes e128
1635
	set mppc yes stateless
1636

    
1637
	set iface group pppoe
1638
	set iface up-script /usr/local/sbin/vpn-linkup-poes
1639
	set iface down-script /usr/local/sbin/vpn-linkdown-poes
1640
	set iface idle 0
1641
	set iface disable on-demand
1642
	set iface disable proxy-arp
1643
	set iface enable tcpmssfix
1644
	set iface mtu 1500
1645

    
1646
	set ipcp no vjcomp
1647
	{$issue_ip_type}
1648
	{$ipcp_dns}
1649

    
1650
	create link template poes_l pppoe
1651
	set link action bundle poes_b
1652

    
1653
	set auth max-logins {$pppoemaxlogins}
1654

    
1655
	set pppoe iface {$pppoe_interface}
1656

    
1657
	set link no multilink
1658
	set link no pap chap
1659
	{$paporchap}
1660
	set link keep-alive 60 180
1661
	set link max-redial -1
1662
	set link mru 1492
1663
	set link latency 1
1664
	set link enable incoming
1665

    
1666
EOD;
1667

    
1668
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1669
				$radiusport = "";
1670
				$radiusacctport = "";
1671
				if (isset($pppoecfg['radius']['server']['port'])) {
1672
					$radiusport = $pppoecfg['radius']['server']['port'];
1673
				}
1674
				if (isset($pppoecfg['radius']['server']['acctport'])) {
1675
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1676
				}
1677
				$mpdconf .=<<<EOD
1678
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1679
	set radius retries 3
1680
	set radius timeout 10
1681
	set auth enable radius-auth
1682

    
1683
EOD;
1684

    
1685
				if (isset ($pppoecfg['radius']['accounting'])) {
1686
					$mpdconf .=<<<EOD
1687
	set auth enable radius-acct
1688

    
1689
EOD;
1690
				}
1691
				if (!empty($pppoecfg['radius']['nasip'])) {
1692
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
1693
				}
1694
			}
1695

    
1696
			fwrite($fd, $mpdconf);
1697
			fclose($fd);
1698
			unset($mpdconf);
1699

    
1700
			if ($pppoecfg['username']) {
1701
				/* write mpd.secret */
1702
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1703
				if (!$fd) {
1704
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1705
					return 1;
1706
				}
1707

    
1708
				$mpdsecret = "\n\n";
1709

    
1710
				if (!empty($pppoecfg['username'])) {
1711
					$item = explode(" ", $pppoecfg['username']);
1712
					foreach ($item as $userdata) {
1713
						$data = explode(":", $userdata);
1714
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1715
					}
1716
				}
1717

    
1718
				fwrite($fd, $mpdsecret);
1719
				fclose($fd);
1720
				unset($mpdsecret);
1721
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1722
			}
1723

    
1724
			/* Check if previous instance is still up */
1725
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
1726
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1727
			}
1728

    
1729
			/* Get support for netgraph(4) from the nic */
1730
			pfSense_ngctl_attach(".", $pppoe_interface);
1731
			/* fire up mpd */
1732
			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");
1733

    
1734
			break;
1735
	}
1736

    
1737
	if (platform_booting()) {
1738
		echo gettext("done") . "\n";
1739
	}
1740

    
1741
	return 0;
1742
}
1743

    
1744
function vpn_l2tp_configure() {
1745
	global $config, $g;
1746

    
1747
	$syscfg = $config['system'];
1748
	$l2tpcfg = $config['l2tp'];
1749

    
1750
	/* create directory if it does not exist */
1751
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
1752
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1753
	}
1754

    
1755
	if (platform_booting()) {
1756
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
1757
			return 0;
1758
		}
1759

    
1760
		echo gettext("Configuring l2tp VPN service... ");
1761
	} else {
1762
		/* kill mpd */
1763
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1764

    
1765
		/* wait for process to die */
1766
		sleep(8);
1767

    
1768
	}
1769

    
1770
	/* make sure l2tp-vpn directory exists */
1771
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn")) {
1772
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1773
	}
1774

    
1775
	switch ($l2tpcfg['mode']) {
1776

    
1777
		case 'server':
1778
			$l2tp_listen="";
1779
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
1780
			if (is_ipaddrv4($ipaddr)) {
1781
				$l2tp_listen="set l2tp self $ipaddr";
1782
			}
1783

    
1784
			switch ($l2tpcfg['paporchap']) {
1785
				case 'chap':
1786
					$paporchap = "set link enable chap";
1787
					break;
1788
				case 'chap-msv2':
1789
					$paporchap = "set link enable chap-msv2";
1790
					break;
1791
				default:
1792
					$paporchap = "set link enable pap";
1793
					break;
1794
			}
1795

    
1796
			/* write mpd.conf */
1797
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1798
			if (!$fd) {
1799
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1800
				return 1;
1801
			}
1802

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

    
1805
			$issue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 ";
1806
			if (isset($l2tpcfg['radius']['radiusissueips']) && isset($l2tpcfg['radius']['server']['enable'])) {
1807
				$issue_ip_type .= "0.0.0.0/0";
1808
			} else {
1809
				$issue_ip_type .= "ippool p0";
1810
			}
1811

    
1812
			$ipcp_dns = '';
1813
			if (is_ipaddr($l2tpcfg['dns1'])) {
1814
				$ipcp_dns = "set ipcp dns " . $l2tpcfg['dns1'];
1815
				if (is_ipaddr($l2tpcfg['dns2'])) {
1816
					$ipcp_dns .= " " . $l2tpcfg['dns2'];
1817
				}
1818
			} elseif (isset ($config['dnsmasq']['enable']) ||
1819
			    isset ($config['unbound']['enable'])) {
1820
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1821
				if ($syscfg['dnsserver'][0]) {
1822
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1823
				}
1824
			} elseif (is_array($syscfg['dnsserver']) &&
1825
			    ($syscfg['dnsserver'][0])) {
1826
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1827
			}
1828

    
1829
			$mpdconf =<<<EOD
1830

    
1831
startup:
1832

    
1833
l2tps:
1834
	set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}
1835

    
1836
	create bundle template l2tp_b
1837
	set bundle enable compression
1838
	set bundle yes crypt-reqd
1839

    
1840
	set ccp yes mppc
1841

    
1842
	set iface name l2tp
1843
	set iface group l2tp
1844
	set iface up-script /usr/local/sbin/vpn-linkup-l2tp
1845
	set iface down-script /usr/local/sbin/vpn-linkdown-l2tp
1846
	set iface disable on-demand
1847
	set iface enable proxy-arp
1848

    
1849
	set ipcp yes vjcomp
1850
	{$issue_ip_type}
1851
	{$ipcp_dns}
1852

    
1853
	create link template l2tp_l l2tp
1854
	set link action bundle l2tp_b
1855

    
1856
	set link yes acfcomp protocomp
1857
	set link enable multilink
1858
	set link no pap chap chap-msv2
1859
	{$paporchap}
1860
	{$l2tp_listen}
1861
	set link keep-alive 10 180
1862
	set link enable incoming
1863

    
1864
EOD;
1865

    
1866

    
1867
			if (isset ($l2tpcfg['radius']['enable'])) {
1868
				$mpdconf .=<<<EOD
1869
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1870
	set radius retries 3
1871
	set radius timeout 10
1872
	set auth disable internal
1873
	set auth enable radius-auth
1874

    
1875
EOD;
1876

    
1877
				if (isset ($l2tpcfg['radius']['accounting'])) {
1878
					$mpdconf .=<<<EOD
1879
	set auth enable radius-acct
1880

    
1881
EOD;
1882
				}
1883
			}
1884

    
1885
			fwrite($fd, $mpdconf);
1886
			fclose($fd);
1887
			unset($mpdconf);
1888

    
1889
			/* write mpd.secret */
1890
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1891
			if (!$fd) {
1892
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1893
				return 1;
1894
			}
1895

    
1896
			$mpdsecret = "\n\n";
1897

    
1898
			if (is_array($l2tpcfg['user'])) {
1899
				foreach ($l2tpcfg['user'] as $user) {
1900
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1901
				}
1902
			}
1903

    
1904
			fwrite($fd, $mpdsecret);
1905
			fclose($fd);
1906
			unset($mpdsecret);
1907
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1908

    
1909
			vpn_netgraph_support();
1910

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

    
1914
			break;
1915

    
1916
		case 'redir':
1917
			break;
1918
	}
1919

    
1920
	if (platform_booting()) {
1921
		echo "done\n";
1922
	}
1923

    
1924
	return 0;
1925
}
1926

    
1927
?>
(49-49/55)