Project

General

Profile

Download (54.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * vpn.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 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
	/* write an eap-radius config section if appropriate */
493
	if (strlen($radius_server_txt) && ($mobile_ipsec_auth === "eap-radius")) {
494
		$strongswan .= <<<EOD
495
		eap-radius {
496
			class_group = yes
497
			eap_start = no
498
			servers {
499
{$radius_server_txt}
500
			}
501
		}
502

    
503
EOD;
504
	}
505

    
506
	if (is_array($a_client) && isset($a_client['enable'])) {
507
		$strongswan .= "\t\tattr {\n";
508

    
509
		$cfgservers = array();
510
		if (!empty($a_client['dns_server1'])) {
511
			$cfgservers[] = $a_client['dns_server1'];
512
		}
513
		if (!empty($a_client['dns_server2'])) {
514
			$cfgservers[] = $a_client['dns_server2'];
515
		}
516
		if (!empty($a_client['dns_server3'])) {
517
			$cfgservers[] = $a_client['dns_server3'];
518
		}
519
		if (!empty($a_client['dns_server4'])) {
520
			$cfgservers[] = $a_client['dns_server4'];
521
		}
522

    
523
		if (!empty($cfgservers)) {
524
			$strongswan .= "\t\t\tdns = " . implode(",", $cfgservers) . "\n";
525
		}
526
		unset($cfgservers);
527
		$cfgservers = array();
528
		if (!empty($a_client['wins_server1'])) {
529
			$cfgservers[] = $a_client['wins_server1'];
530
		}
531
		if (!empty($a_client['wins_server2'])) {
532
			$cfgservers[] = $a_client['wins_server2'];
533
		}
534
		if (!empty($cfgservers)) {
535
			$strongswan .= "\t\t\tnbns = " . implode(",", $cfgservers) . "\n";
536
		}
537
		unset($cfgservers);
538

    
539
		if (isset($a_client['net_list']) && is_array($a_phase2)) {
540
			$net_list = '';
541
			foreach ($a_phase2 as $ph2ent) {
542
				if (isset($ph2ent['disabled'])) {
543
					continue;
544
				}
545

    
546
				if (!isset($ph2ent['mobile'])) {
547
					continue;
548
				}
549

    
550
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
551

    
552
				if (!empty($net_list)) {
553
					$net_list .= ",";
554
				}
555
				$net_list .= $localid;
556
			}
557

    
558
			if (!empty($net_list)) {
559
				$strongswan .= "\t\t\tsubnet = {$net_list}\n";
560
				$strongswan .= "\t\t\tsplit-include = {$net_list}\n";
561
				unset($net_list);
562
			}
563
		}
564

    
565
		if (!empty($a_client['dns_domain'])) {
566
			$strongswan .= "\t\t\t# Search domain and default domain\n";
567
			$strongswan .= "\t\t\t28674 = \"{$a_client['dns_domain']}\"\n";
568
			if (empty($a_client['dns_split'])) {
569
				$strongswan .= "\t\t\t28675 = \"{$a_client['dns_domain']}\"";
570
			}
571
			$strongswan .= "\n";
572
		}
573

    
574
		if (!empty($a_client['dns_split'])) {
575
			$strongswan .= "\t\t\t28675 = {$a_client['dns_split']}\n";
576
		}
577

    
578
		if (!empty($a_client['login_banner'])) {
579
			$strongswan .= "\t\t\t28672 = \"{$a_client['login_banner']}\"\n";
580
		}
581

    
582
		if (isset($a_client['save_passwd'])) {
583
			$strongswan .= "\t\t\t28673 = 1\n";
584
		}
585

    
586
		if ($a_client['pfs_group']) {
587
			$strongswan .= "\t\t\t28679 = \"{$a_client['pfs_group']}\"\n";
588
		}
589
		$strongswan .= "\t\t}\n";
590

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

    
612
	$strongswan .= "\n\t}\n}\n";
613
	@file_put_contents("{$g['varetc_path']}/ipsec/strongswan.conf", $strongswan);
614
	unset($strongswan);
615

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

    
631
	$pskconf = "";
632

    
633
	$vpncas = array();
634
	if (is_array($a_phase1) && count($a_phase1)) {
635
		foreach ($a_phase1 as $ph1ent) {
636

    
637
			if (isset($ph1ent['disabled'])) {
638
				continue;
639
			}
640

    
641
			if (strstr($ph1ent['authentication_method'], 'rsa') ||
642
			    in_array($ph1ent['authentication_method'], array('eap-mschapv2', 'eap-tls', 'eap-radius'))) {
643
				$certline = '';
644

    
645
				$ikeid = $ph1ent['ikeid'];
646
				$cert = lookup_cert($ph1ent['certref']);
647

    
648
				if (!$cert) {
649
					log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
650
					continue;
651
				}
652

    
653
				/* add signing CA cert chain of server cert
654
				 * to the list of CAs to write
655
				 */
656
				$cachain = ca_chain_array($cert);
657
				if ($cachain && is_array($cachain)) {
658
					foreach ($cachain as $cacrt) {
659
						$vpncas[$cacrt['refid']] = $cacrt;
660
					}
661
				}
662

    
663
				@chmod($certpath, 0600);
664

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

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

    
680
				/* XXX" Traffic selectors? */
681
				$pskconf .= " : RSA {$ph1keyfile}\n";
682
			} else {
683
				list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local');
684
				list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap);
685

    
686
				$myid = trim($myid_data);
687

    
688
				if (empty($peerid_data)) {
689
					continue;
690
				}
691

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

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

    
698
				$peerid = ($peerid_data != 'allusers') ? trim($peerid_data) : '';
699

    
700
				if ($peerid_type == 'fqdn' && !empty($peerid)) {
701
					$peerid = "@{$peerid}";
702
				}
703

    
704
				if (!empty($ph1ent['pre-shared-key'])) {
705
					$pskconf .= "{$myid} {$peerid} : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n";
706
					if (isset($ph1ent['mobile'])) {
707
						$pskconf .= " : PSK 0s" . base64_encode(trim($ph1ent['pre-shared-key'])) . "\n";
708
					}
709
				}
710
			}
711

    
712
			/* if the client authenticates with a cert add the
713
			 * client cert CA chain to the list of CAs to write
714
			 */
715
			if (in_array($ph1ent['authentication_method'],
716
			array('rsasig', 'eap-tls', 'xauth_rsa_server'))) {
717

    
718
				if (!empty($ph1ent['caref']) && !array_key_exists($ph1ent['caref'], $vpncas)) {
719
					$thisca = lookup_ca($ph1ent['caref']);
720
					$vpncas[$ph1ent['caref']] = $thisca;
721

    
722
					/* follow chain up to root */
723
					$cachain = ca_chain_array($thisca);
724
					if ($cachain and is_array($cachain)) {
725
						foreach ($cachain as $cacrt) {
726
							$vpncas[$cacrt['refid']] = $cacrt;
727
						}
728
					}
729
				}
730
			}
731
		}
732
	}
733

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

    
749
	/* Add user PSKs */
750
	if (is_array($config['system']) && is_array($config['system']['user'])) {
751
		foreach ($config['system']['user'] as $user) {
752
			if (!empty($user['ipsecpsk'])) {
753
				$pskconf .= "{$myid} {$user['name']} : PSK 0s" . base64_encode($user['ipsecpsk']) . "\n";
754
			}
755
		}
756
		unset($user);
757
	}
758

    
759
	/* add PSKs for mobile clients */
760
	if (is_array($ipseccfg['mobilekey'])) {
761
		foreach ($ipseccfg['mobilekey'] as $key) {
762
			if ($key['ident'] == "allusers") {
763
				$key['ident'] = '%any';
764
			}
765
			if ($key['ident'] == "any") {
766
				$key['ident'] = '%any';
767
			}
768
			if (empty($key['type'])) {
769
				$key['type'] = 'PSK';
770
			}
771
			$pskconf .= " {$key['ident']} : {$key['type']} 0s" . base64_encode($key['pre-shared-key']) . "\n";
772
		}
773
		unset($key);
774
	}
775

    
776
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.secrets", $pskconf);
777
	chmod("{$g['varetc_path']}/ipsec/ipsec.secrets", 0600);
778
	unset($pskconf);
779

    
780
	$uniqueids = 'yes';
781
	if (!empty($config['ipsec']['uniqueids'])) {
782
		if (array_key_exists($config['ipsec']['uniqueids'], $ipsec_idhandling)) {
783
			$uniqueids = $config['ipsec']['uniqueids'];
784
		}
785
	}
786
	$natfilterrules = false;
787
	/* begin ipsec.conf */
788
	$ipsecconf = "";
789
	$enablecompression = false;
790
	if (is_array($a_phase1) && count($a_phase1)) {
791

    
792
		$ipsecconf .= "# This file is automatically generated. Do not edit\n";
793
		$ipsecconf .= "config setup\n\tuniqueids = {$uniqueids}\n";
794

    
795
		if (isset($config['ipsec']['strictcrlpolicy'])) {
796
			$ipsecconf .= "\tstrictcrlpolicy = yes \n";
797
		}
798

    
799
		if (!isset($config['ipsec']['noshuntlaninterfaces'])) {
800
			if ($config['interfaces']['lan']) {
801
				$lanip = get_interface_ip("lan");
802
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
803
					$lansn = get_interface_subnet("lan");
804
					$lansa = gen_subnet($lanip, $lansn);
805
					$ipsecconf .= <<<EOD
806

    
807
conn bypasslan
808
	leftsubnet = {$lansa}/{$lansn}
809
	rightsubnet = {$lansa}/{$lansn}
810
	authby = never
811
	type = passthrough
812
	auto = route
813

    
814
EOD;
815
				}
816
			}
817
		}
818

    
819
		foreach ($a_phase1 as $ph1ent) {
820
			if (isset($ph1ent['disabled'])) {
821
				continue;
822
			}
823

    
824
			if ($ph1ent['mode'] == "aggressive") {
825
				$aggressive = "yes";
826
			} else {
827
				$aggressive = "no";
828
			}
829

    
830
			$ep = ipsec_get_phase1_src($ph1ent);
831
			if (!$ep) {
832
				continue;
833
			}
834

    
835
			$ikeid = $ph1ent['ikeid'];
836
			$keyexchange = "ikev1";
837
			$passive = "route";
838
			if (!empty($ph1ent['iketype'])) {
839
				if ($ph1ent['iketype'] == "ikev2") {
840
					$keyexchange = "ikev2";
841
				} elseif ($ph1ent['iketype'] == "auto") {
842
					$keyexchange = "ike";
843
				}
844
			}
845

    
846
			if (isset($ph1ent['mobile'])) {
847
				$right_spec = "%any";
848
				$passive = 'add';
849
			} else {
850
				if (isset($ph1ent['responderonly'])) {
851
					$passive = 'add';
852
				}
853

    
854
				$right_spec = $ph1ent['remote-gateway'];
855
				if (is_ipaddr($right_spec)) {
856
					$sourcehost = $right_spec;
857
				} else {
858
					$sourcehost = $rgmap['remote-gateway'];
859
				}
860

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

    
908
			list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, 'local');
909
			if ($myid_type != 'address' && $myid_type != 'keyid' && $myid_type != 'asn1dn') {
910
				$myid_data = "{$myid_type}:{$myid_data}";
911
			} elseif ($myid_type == "asn1dn" && !empty($myid_data)) {
912
				if ($myid_data[0] == '#') {
913
				/* asn1dn needs double quotes */
914
					$myid_data = "\"{$myid_type}:{$myid_data}\"";
915
				} else {
916
					$myid_data = "\"{$myid_data}\"";
917
				}
918
			}
919
			$leftid = '';
920
			if (!empty($myid_data)) {
921
				$leftid = "leftid = {$myid_data}";
922
			}
923

    
924
			$peerid_spec = '';
925
			if (isset($ph1ent['mobile']) && ($ph1ent['authentication_method'] == "pre_shared_key" || $ph1ent['authentication_method'] == "xauth_psk_server")) {
926
				// Only specify peer ID if we are not dealing with mobile PSK
927
			} else {
928
				list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, 'peer', $rgmap);
929
				if ($peerid_type == 'any') {
930
					$peerid_spec = '';
931
				} elseif ($peerid_type != 'address' && $peerid_type != 'keyid' && $peerid_type != 'asn1dn') {
932
					$peerid_spec = "{$peerid_type}:{$peerid_data}";
933
				} elseif ($peerid_type == "asn1dn") {
934
					/* asn1dn needs double quotes */
935
					if ($peerid_data[0] == '#') {
936
						$peerid_spec = "\"{$peerid_type}:{$peerid_data}\"";
937
					} elseif (!empty($peerid_data)) {
938
						$peerid_spec = "\"{$peerid_data}\"";
939
					}
940
				} else {
941
					$peerid_spec = $peerid_data;
942
				}
943
			}
944

    
945
			if (is_array($ph1ent['encryption-algorithm']) && !empty($ph1ent['encryption-algorithm']['name']) && !empty($ph1ent['hash-algorithm'])) {
946
				$ealgosp1 = '';
947
				$ealg_id = $ph1ent['encryption-algorithm']['name'];
948
				$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
949
				if ($ealg_kl) {
950
					$ealgosp1 = "ike = {$ealg_id}{$ealg_kl}-{$ph1ent['hash-algorithm']}";
951
				} else {
952
					$ealgosp1 = "ike = {$ealg_id}-{$ph1ent['hash-algorithm']}";
953
				}
954

    
955
				$modp = vpn_ipsec_convert_to_modp($ph1ent['dhgroup']);
956
				if (!empty($modp)) {
957
					$ealgosp1 .= "-{$modp}";
958
				}
959

    
960
				$ealgosp1 .= "!";
961
			}
962

    
963
			if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
964
				if ($passive == "route") {
965
					$dpdline = "dpdaction = restart";
966
				} else {
967
					$dpdline = "dpdaction = clear";
968
				}
969
				$dpdline .= "\n\tdpddelay = {$ph1ent['dpd_delay']}s";
970
				$dpdtimeout = $ph1ent['dpd_delay'] * ($ph1ent['dpd_maxfail'] + 1);
971
				$dpdline .= "\n\tdpdtimeout = {$dpdtimeout}s";
972
			} else {
973
				$dpdline = "dpdaction = none";
974
			}
975

    
976
			$ikelifeline = '';
977
			if ($ph1ent['lifetime']) {
978
				$ikelifeline = "ikelifetime = {$ph1ent['lifetime']}s";
979
			}
980

    
981
			$rightsourceip = NULL;
982
			if (isset($ph1ent['mobile'])) {
983
				$rightsourceips = array();
984
				if (!empty($a_client['pool_address'])) {
985
					$rightsourceips[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
986
				}
987
				if (!empty($a_client['pool_address_v6'])) {
988
					$rightsourceips[] = "{$a_client['pool_address_v6']}/{$a_client['pool_netbits_v6']}";
989
				}
990
				if ($ph1ent['authentication_method'] == "eap-radius" && !count($rightsourceips)) {
991
					$rightsourceips[] = "%radius";
992
				}
993
				if (count($rightsourceips)) {
994
					$rightsourceip = "\trightsourceip = " . implode(',', $rightsourceips) . "\n";
995
				}
996
			}
997

    
998
			if (!empty($ph1ent['caref'])) {
999
				$ca = lookup_ca($ph1ent['caref']);
1000
				if ($ca) {
1001
					$casubarr = cert_get_subject_array($ca['crt']);
1002
					$casub = "";
1003
					foreach ($casubarr as $casubfield) {
1004
						if (empty($casub)) {
1005
							$casub = "/";
1006
						}
1007
						$casub .= "{$casubfield['a']}={$casubfield['v']}/";
1008
					}
1009

    
1010
				}
1011
			}
1012

    
1013
			$authentication = "";
1014
			switch ($ph1ent['authentication_method']) {
1015
				case 'eap-mschapv2':
1016
					if (isset($ph1ent['mobile'])) {
1017
						$authentication = "eap_identity=%any\n\t";
1018
						$authentication .= "leftauth=pubkey\n\trightauth=eap-mschapv2";
1019
						if (!empty($ph1ent['certref'])) {
1020
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1021
							$authentication .= "\n\tleftsendcert=always";
1022
						}
1023
					}
1024
					break;
1025
				case 'eap-tls':
1026
					if (isset($ph1ent['mobile'])) {
1027
						$authentication = "eap_identity=%identity\n\t";
1028
						$authentication .= "leftauth=pubkey\n\trightauth=eap-tls";
1029
						if (!empty($ph1ent['certref'])) {
1030
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1031
							$authentication .= "\n\tleftsendcert=always";
1032
						}
1033
					} else {
1034
						$authentication = "leftauth=eap-tls\n\trightauth=eap-tls";
1035
						if (!empty($ph1ent['certref'])) {
1036
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1037
							$authentication .= "\n\tleftsendcert=always";
1038
						}
1039
					}
1040
					if (isset($casub)) {
1041
						$authentication .= "\n\trightca=\"$casub\"";
1042
					}
1043
					break;
1044
				case 'eap-radius':
1045
					if (isset($ph1ent['mobile'])) {
1046
						$authentication = "eap_identity=%identity\n\t";
1047
						$authentication .= "leftauth=pubkey\n\trightauth=eap-radius";
1048
						if (!empty($ph1ent['certref'])) {
1049
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1050
							$authentication .= "\n\tleftsendcert=always";
1051
						}
1052
					} else {
1053
						$authentication = "leftauth=eap-radius\n\trightauth=eap-radius";
1054
						if (!empty($ph1ent['certref'])) {
1055
							$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1056
							$authentication .= "\n\tleftsendcert=always";
1057
						}
1058
					}
1059
					break;
1060
				case 'xauth_rsa_server':
1061
					$authentication = "leftauth = pubkey\n\trightauth = pubkey";
1062
					$authentication .= "\n\trightauth2 = xauth-generic";
1063
					if (!empty($ph1ent['certref'])) {
1064
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1065
						$authentication .= "\n\tleftsendcert=always";
1066
					}
1067
					if (isset($casub)) {
1068
						$authentication .= "\n\trightca=\"$casub\"";
1069
					}
1070
					break;
1071
				case 'xauth_psk_server':
1072
					$authentication = "leftauth = psk\n\trightauth = psk";
1073
					$authentication .= "\n\trightauth2 = xauth-generic";
1074
					break;
1075
				case 'pre_shared_key':
1076
					$authentication = "leftauth = psk\n\trightauth = psk";
1077
					break;
1078
				case 'rsasig':
1079
					$authentication = "leftauth = pubkey\n\trightauth = pubkey";
1080
					if (!empty($ph1ent['certref'])) {
1081
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1082
						$authentication .= "\n\tleftsendcert=always";
1083
					}
1084
					if (isset($casub)) {
1085
						$authentication .= "\n\trightca=\"$casub\"";
1086
					}
1087
					break;
1088
				case 'hybrid_rsa_server':
1089
					$authentication = "leftauth = pubkey\n\trightauth = xauth-generic";
1090
					if (!empty($ph1ent['certref'])) {
1091
						$authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
1092
						$authentication .= "\n\tleftsendcert=always";
1093
					}
1094
					break;
1095
			}
1096

    
1097
			$left_spec = $ep;
1098

    
1099
			if (isset($ph1ent['reauth_enable'])) {
1100
				$reauth = "reauth = no";
1101
			} else {
1102
				$reauth = "reauth = yes";
1103
			}
1104
			if (isset($ph1ent['rekey_enable'])) {
1105
				$rekey = "rekey = no";
1106
			} else {
1107
				$rekey = "rekey = yes";
1108
			}
1109

    
1110
			if ($ph1ent['nat_traversal'] == 'off') {
1111
				$forceencaps = 'forceencaps = no';
1112
			} else if ($ph1ent['nat_traversal'] == 'force') {
1113
				$forceencaps = 'forceencaps = yes';
1114
			} else {
1115
				$forceencaps = 'forceencaps = no';
1116
			}
1117

    
1118
			if ($ph1ent['mobike'] == 'on') {
1119
				$mobike = 'mobike = yes';
1120
			} else {
1121
				$mobike = 'mobike = no';
1122
			}
1123

    
1124
			if (isset($ph1ent['tfc_enable'])) {
1125
				if (isset($ph1ent['tfc_bytes']) && is_numericint($ph1ent['tfc_bytes'])) {
1126
					$tfc = "tfc = {$ph1ent['tfc_bytes']}";
1127
				} else {
1128
					$tfc = "tfc = %mtu";
1129
				}
1130
			}
1131

    
1132
			$ipseclifetime = 0;
1133
			$rightsubnet_spec = array();
1134
			$leftsubnet_spec = array();
1135
			$reqids = array();
1136
			$ealgoAHsp2arr = array();
1137
			$ealgoESPsp2arr = array();
1138
			if (is_array($a_phase2) && count($a_phase2)) {
1139
				foreach ($a_phase2 as $ph2ent) {
1140
					if ($ikeid != $ph2ent['ikeid']) {
1141
						continue;
1142
					}
1143

    
1144
					if (isset($ph2ent['disabled'])) {
1145
						continue;
1146
					}
1147

    
1148
					if (isset($ph2ent['mobile']) && !isset($a_client['enable'])) {
1149
						continue;
1150
					}
1151

    
1152
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
1153
						$tunneltype = "type = tunnel";
1154

    
1155
						$localid_type = $ph2ent['localid']['type'];
1156
						$leftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']);
1157

    
1158
						/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
1159
						if (($localid_type == "none" || $localid_type == "mobile") &&
1160
						    isset($ph1ent['mobile']) && (ipsec_get_number_of_phase2($ikeid) == 1)) {
1161
							$left_spec = '%any';
1162
						} else {
1163
							if ($localid_type != "address") {
1164
								$localid_type = "subnet";
1165
							}
1166
							// Don't let an empty subnet into config, it can cause parse errors. Ticket #2201.
1167
							if (!is_ipaddr($leftsubnet_data) && !is_subnet($leftsubnet_data) && ($leftsubnet_data != "0.0.0.0/0")) {
1168
								log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet.");
1169
								continue;
1170
							}
1171
							if (!empty($ph2ent['natlocalid'])) {
1172
								$natleftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], false, $ph2ent['mode']);
1173
								if ($ph2ent['natlocalid']['type'] != "address") {
1174
									if (is_subnet($natleftsubnet_data)) {
1175
										$leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}";
1176
									}
1177
								} else {
1178
									if (is_ipaddr($natleftsubnet_data)) {
1179
										$leftsubnet_data = "{$natleftsubnet_data}|{$leftsubnet_data}";
1180
									}
1181
								}
1182
								$natfilterrules = true;
1183
							}
1184
						}
1185

    
1186
						$leftsubnet_spec[] = $leftsubnet_data;
1187

    
1188
						if (!isset($ph2ent['mobile'])) {
1189
							$tmpsubnet = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
1190
							$rightsubnet_spec[] = $tmpsubnet;
1191
						} else if (!empty($a_client['pool_address'])) {
1192
							$rightsubnet_spec[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
1193
						}
1194
					} else {
1195
						$tunneltype = "type = transport";
1196

    
1197
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
1198
						    ($ph1ent['authentication_method'] == "pre_shared_key")) &&
1199
						    isset($ph1ent['mobile'])) {
1200
							$left_spec = "%any";
1201
						} else {
1202
							$tmpsubnet = ipsec_get_phase1_src($ph1ent);
1203
							$leftsubnet_spec[] = $tmpsubnet;
1204
						}
1205

    
1206
						if (!isset($ph2ent['mobile'])) {
1207
							$rightsubnet_spec[] = $right_spec;
1208
						}
1209
					}
1210

    
1211
					if (isset($a_client['pfs_group']) && isset($ph2ent['mobile'])) {
1212
						$ph2ent['pfsgroup'] = $a_client['pfs_group'];
1213
					}
1214

    
1215
					if ($ph2ent['protocol'] == 'esp') {
1216
						if (is_array($ph2ent['encryption-algorithm-option'])) {
1217
							foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
1218
								$ealg_id = $ealg['name'];
1219
								$ealg_kl = $ealg['keylen'];
1220

    
1221
								if (!empty($ealg_kl) && $ealg_kl == "auto") {
1222
									if (empty($p2_ealgos) || !is_array($p2_ealgos)) {
1223
										require_once("ipsec.inc");
1224
									}
1225
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
1226
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
1227
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
1228
									/* XXX: in some cases where include ordering is suspect these variables
1229
									 * are somehow 0 and we enter this loop forever and timeout after 900
1230
									 * seconds wrecking bootup */
1231
									if ($key_hi != 0 and $key_lo != 0 and $key_step != 0) {
1232
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
1233
											if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1234
												foreach ($ph2ent['hash-algorithm-option'] as $halgo) {
1235
													$halgo = str_replace('hmac_', '', $halgo);
1236
													$tmpealgo = "{$ealg_id}{$keylen}-{$halgo}";
1237
													$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1238
													if (!empty($modp)) {
1239
														$tmpealgo .= "-{$modp}";
1240
													}
1241
													$ealgoESPsp2arr[] = $tmpealgo;
1242
												}
1243
											} else {
1244
												$tmpealgo = "{$ealg_id}{$keylen}";
1245
												$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1246
												if (!empty($modp)) {
1247
													$tmpealgo .= "-{$modp}";
1248
												}
1249
												$ealgoESPsp2arr[] = $tmpealgo;
1250
											}
1251
										}
1252
									}
1253
								} else {
1254
									if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1255
										foreach ($ph2ent['hash-algorithm-option'] as $halgo) {
1256
											$halgo = str_replace('hmac_', '', $halgo);
1257
											$tmpealgo = "{$ealg_id}{$ealg_kl}-{$halgo}";
1258
											$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1259
											if (!empty($modp)) {
1260
												$tmpealgo .= "-{$modp}";
1261
											}
1262
											$ealgoESPsp2arr[] = $tmpealgo;
1263
										}
1264
									} else {
1265
										$tmpealgo = "{$ealg_id}{$ealg_kl}";
1266
										$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1267
										if (!empty($modp)) {
1268
											$tmpealgo .= "-{$modp}";
1269
										}
1270
										$ealgoESPsp2arr[] = $tmpealgo;
1271
									}
1272
								}
1273
							}
1274
						}
1275
					} else if ($ph2ent['protocol'] == 'ah') {
1276
						if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
1277
							$modp = vpn_ipsec_convert_to_modp($ph2ent['pfsgroup']);
1278
							foreach ($ph2ent['hash-algorithm-option'] as $tmpAHalgo) {
1279
								$tmpAHalgo = str_replace('hmac_', '', $tmpAHalgo);
1280
								if (!empty($modp)) {
1281
									$tmpAHalgo = "-{$modp}";
1282
								}
1283
								$ealgoAHsp2arr[] = $tmpAHalgo;
1284
							}
1285
						}
1286
					}
1287

    
1288
					$reqids[] = $ph2ent['reqid'];
1289

    
1290
					if (!empty($ph2ent['lifetime'])) {
1291
						if ($ipseclifetime == 0 || intval($ipseclifetime) > intval($ph2ent['lifetime'])) {
1292
							$ipseclifetime = intval($ph2ent['lifetime']);
1293
						}
1294
					}
1295

    
1296
				}
1297
			}
1298

    
1299
			$ipsecconnect =<<<EOD
1300
	fragmentation = yes
1301
	keyexchange = {$keyexchange}
1302
	{$reauth}
1303
	{$forceencaps}
1304
	{$mobike}
1305
	{$tfc}
1306
	{$rekey}
1307
	installpolicy = yes
1308
	{$tunneltype}
1309
	{$dpdline}
1310
	auto = {$passive}
1311
	left = {$left_spec}
1312
	right = {$right_spec}
1313
	{$leftid}
1314

    
1315
EOD;
1316

    
1317
			/* Disable ipcomp for now. redmine #6167
1318
			if (isset($config['ipsec']['compression'])) {
1319
				$ipsecconnect .= "\tcompress = yes\n";
1320
				$enablecompression = true;
1321
			} */
1322
			if (!empty($ikelifeline)) {
1323
				$ipsecconnect .= "\t{$ikelifeline}\n";
1324
			}
1325
			if ($ipseclifetime > 0) {
1326
				$ipsecconnect .= "\tlifetime = {$ipseclifetime}s\n";
1327
			}
1328
			if (!empty($rightsourceip)) {
1329
				$ipsecconnect .= "{$rightsourceip}";
1330
			}
1331
			if (!empty($ealgosp1)) {
1332
				$ipsecconnect .= "\t{$ealgosp1}\n";
1333
			}
1334
			if (!empty($ealgoAHsp2arr)) {
1335
				$ipsecconnect .= "\tah = " . join(',', $ealgoAHsp2arr) . "!\n";
1336
			}
1337
			if (!empty($ealgoESPsp2arr)) {
1338
				$ipsecconnect .= "\tesp = " . join(',', $ealgoESPsp2arr) . "!\n";
1339
			}
1340
			if (!empty($authentication)) {
1341
				$ipsecconnect .= "\t{$authentication}\n";
1342
			}
1343
			if (!empty($peerid_spec)) {
1344
				$ipsecconnect .= "\trightid = {$peerid_spec}\n";
1345
			}
1346
			if ($keyexchange != 'ikev2') {
1347
				$ipsecconnect .= "\taggressive = {$aggressive}\n";
1348
			}
1349

    
1350
			if (!isset($ph1ent['mobile']) && ($keyexchange == 'ikev1' || isset($ph1ent['splitconn']))) {
1351
				if (!empty($rightsubnet_spec)) {
1352
					$ipsecfin = '';
1353
					foreach ($rightsubnet_spec as $idx => $rsubnet) {
1354
						$ipsecfin .= "\nconn con{$ph1ent['ikeid']}00{$idx}\n";
1355
						//if (!empty($reqids[$idx])) {
1356
						//	$ipsecfin .= "\treqid = " . $reqids[$idx] . "\n";
1357
						//}
1358
						$ipsecfin .= $ipsecconnect;
1359
						$ipsecfin .= "\trightsubnet = {$rsubnet}\n";
1360
						$ipsecfin .= "\tleftsubnet = " . $leftsubnet_spec[$idx] . "\n";
1361
					}
1362
				} else {
1363
					log_error(sprintf(gettext("No phase2 specifications for tunnel with REQID = %s"), $ikeid));
1364
				}
1365
			} else {
1366
				$ipsecfin = "\nconn con{$ph1ent['ikeid']}\n";
1367
				//if (!empty($reqids[$idx])) {
1368
				//	$ipsecfin .= "\treqid = " . $reqids[0] . "\n";
1369
				//}
1370
				$ipsecfin .= $ipsecconnect;
1371
				if (!isset($ph1ent['mobile']) && !empty($rightsubnet_spec)) {
1372
					$tempsubnets = array();
1373
					foreach ($rightsubnet_spec as $rightsubnet) {
1374
						$tempsubnets[$rightsubnet] = $rightsubnet;
1375
					}
1376
					$ipsecfin .= "\trightsubnet = " . join(",", $tempsubnets) . "\n";
1377
					unset($tempsubnets, $rightsubnet);
1378
				}
1379
				if (!empty($leftsubnet_spec)) {
1380
					$tempsubnets = array();
1381
					foreach ($leftsubnet_spec as $leftsubnet) {
1382
						$tempsubnets[$leftsubnet] = $leftsubnet;
1383
					}
1384
					$ipsecfin .= "\tleftsubnet = " . join(",", $tempsubnets) . "\n";
1385
					unset($tempsubnets, $leftsubnet);
1386
				}
1387
			}
1388
			$ipsecconf .= $ipsecfin;
1389
			unset($ipsecfin);
1390
		}
1391
	}
1392

    
1393
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.conf", $ipsecconf);
1394
	unset($ipsecconf);
1395
	/* end ipsec.conf */
1396

    
1397
	if ($enablecompression === true) {
1398
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 1);
1399
	} else {
1400
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 0);
1401
	}
1402

    
1403
	/* manage process */
1404
	if ($restart === true) {
1405
		mwexec("/usr/local/sbin/ipsec restart", false);
1406
	} else {
1407
		if (isvalidpid("{$g['varrun_path']}/starter.charon.pid")) {
1408
			/* Update configuration changes */
1409
			/* Read secrets */
1410
			mwexec("/usr/local/sbin/ipsec rereadall", false);
1411
			mwexec("/usr/local/sbin/ipsec reload", false);
1412
		} else {
1413
			mwexec("/usr/local/sbin/ipsec start", false);
1414
		}
1415
	}
1416

    
1417
	// run ping_hosts.sh once if it's enabled to avoid wait for minicron
1418
	if ($ipsecpinghostsactive == true) {
1419
		mwexec_bg("/usr/local/bin/ping_hosts.sh");
1420
	}
1421

    
1422
	if ($natfilterrules == true) {
1423
		filter_configure();
1424
	}
1425
	/* start filterdns, if necessary */
1426
	if (count($filterdns_list) > 0) {
1427
		$interval = 60;
1428
		if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval'])) {
1429
			$interval = $ipseccfg['dns-interval'];
1430
		}
1431

    
1432
		$hostnames = "";
1433
		array_unique($filterdns_list);
1434
		foreach ($filterdns_list as $hostname) {
1435
			$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
1436
		}
1437
		file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
1438
		unset($hostnames);
1439

    
1440
		if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid")) {
1441
			sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
1442
		} else {
1443
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
1444
		}
1445
	} else {
1446
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
1447
		@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
1448
	}
1449

    
1450
	if (platform_booting()) {
1451
		echo "done\n";
1452
	}
1453

    
1454
	unlock($ipsecstartlock);
1455
	return count($filterdns_list);
1456
}
1457

    
1458
/*
1459
 * Forcefully restart IPsec
1460
 * This is required for when dynamic interfaces reload
1461
 * For all other occasions the normal vpn_ipsec_configure()
1462
 * will gracefully reload the settings without restarting
1463
 */
1464
function vpn_ipsec_force_reload($interface = "") {
1465
	global $g, $config;
1466

    
1467
	if (!ipsec_enabled()) {
1468
		return;
1469
	}
1470

    
1471
	$ipseccfg = $config['ipsec'];
1472

    
1473
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1474
		$found = false;
1475
		foreach ($ipseccfg['phase1'] as $ipsec) {
1476
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1477
				$found = true;
1478
				break;
1479
			}
1480
		}
1481
		if (!$found) {
1482
			log_error(sprintf(gettext("Ignoring IPsec reload since there are no tunnels on interface %s"), $interface));
1483
			return;
1484
		}
1485
	}
1486

    
1487
	/* If we get this far then we need to take action. */
1488
	log_error(gettext("Forcefully reloading IPsec"));
1489
	vpn_ipsec_configure();
1490
}
1491

    
1492
/* master setup for vpn (mpd) */
1493
function vpn_setup() {
1494
	/* start pppoe server */
1495
	vpn_pppoes_configure();
1496

    
1497
	/* setup l2tp */
1498
	vpn_l2tp_configure();
1499
}
1500

    
1501
function vpn_netgraph_support() {
1502
	$iflist = get_configured_interface_list();
1503
	foreach ($iflist as $iface) {
1504
		$realif = get_real_interface($iface);
1505
		/* Get support for netgraph(4) from the nic */
1506
		$ifinfo = pfSense_get_interface_addresses($realif);
1507
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge"))) {
1508
			pfSense_ngctl_attach(".", $realif);
1509
		}
1510
	}
1511
}
1512

    
1513
function vpn_pppoes_configure() {
1514
	global $config;
1515

    
1516
	if (is_array($config['pppoes']['pppoe'])) {
1517
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
1518
			vpn_pppoe_configure($pppoe);
1519
		}
1520
	}
1521
}
1522

    
1523
function vpn_pppoe_configure(&$pppoecfg) {
1524
	global $config, $g;
1525

    
1526
	$syscfg = $config['system'];
1527

    
1528
	/* create directory if it does not exist */
1529
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
1530
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1531
	}
1532

    
1533
	if (platform_booting()) {
1534
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
1535
			return 0;
1536
		}
1537

    
1538
		echo gettext("Configuring PPPoE Server service... ");
1539
	} else {
1540
		/* kill mpd */
1541
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1542

    
1543
		/* wait for process to die */
1544
		sleep(2);
1545

    
1546
	}
1547

    
1548
	switch ($pppoecfg['mode']) {
1549

    
1550
		case 'server':
1551

    
1552
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1553

    
1554
			if ($pppoecfg['paporchap'] == "chap") {
1555
				$paporchap = "set link enable chap";
1556
			} else {
1557
				$paporchap = "set link enable pap";
1558
			}
1559

    
1560
			/* write mpd.conf */
1561
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1562
			if (!$fd) {
1563
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1564
				return 1;
1565
			}
1566

    
1567
			$issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 ";
1568
			if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1569
				$issue_ip_type .= "0.0.0.0/0";
1570
			} else {
1571
				$issue_ip_type .= "ippool p0";
1572
			}
1573

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

    
1576
			if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
1577
				$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
1578
			} else {
1579
				$pppoemaxlogins = 1;
1580
			}
1581

    
1582
			$ipcp_dns = '';
1583
			if (!empty($pppoecfg['dns1'])) {
1584
				$ipcp_dns = "set ipcp dns " . $pppoecfg['dns1'];
1585
				if (!empty($pppoecfg['dns2'])) {
1586
					$ipcp_dns .= " " . $pppoecfg['dns2'];
1587
				}
1588
			} elseif (isset($config['dnsmasq']['enable']) ||
1589
			    isset ($config['unbound']['enable'])) {
1590
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1591
				if ($syscfg['dnsserver'][0]) {
1592
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1593
				}
1594
			} elseif (is_array($syscfg['dnsserver']) &&
1595
			    ($syscfg['dnsserver'][0])) {
1596
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1597
			}
1598

    
1599
			$mpdconf = <<<EOD
1600
startup:
1601

    
1602
poes:
1603
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
1604

    
1605
	create bundle template poes_b
1606
	set bundle enable compression
1607

    
1608
	set ccp yes mppc
1609
	set mppc yes e40
1610
	set mppc yes e128
1611
	set mppc yes stateless
1612

    
1613
	set iface group pppoe
1614
	set iface up-script /usr/local/sbin/vpn-linkup
1615
	set iface down-script /usr/local/sbin/vpn-linkdown
1616
	set iface idle 0
1617
	set iface disable on-demand
1618
	set iface disable proxy-arp
1619
	set iface enable tcpmssfix
1620
	set iface mtu 1500
1621

    
1622
	set ipcp no vjcomp
1623
	{$issue_ip_type}
1624
	{$ipcp_dns}
1625

    
1626
	create link template poes_l pppoe
1627
	set link action bundle poes_b
1628

    
1629
	set auth max-logins {$pppoemaxlogins}
1630

    
1631
	set pppoe iface {$pppoe_interface}
1632

    
1633
	set link no multilink
1634
	set link no pap chap
1635
	{$paporchap}
1636
	set link keep-alive 60 180
1637
	set link max-redial -1
1638
	set link mru 1492
1639
	set link latency 1
1640
	set link enable incoming
1641

    
1642
EOD;
1643

    
1644
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1645
				$radiusport = "";
1646
				$radiusacctport = "";
1647
				if (isset($pppoecfg['radius']['server']['port'])) {
1648
					$radiusport = $pppoecfg['radius']['server']['port'];
1649
				}
1650
				if (isset($pppoecfg['radius']['server']['acctport'])) {
1651
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1652
				}
1653
				$mpdconf .=<<<EOD
1654
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1655
	set radius retries 3
1656
	set radius timeout 10
1657
	set auth enable radius-auth
1658

    
1659
EOD;
1660

    
1661
				if (isset ($pppoecfg['radius']['accounting'])) {
1662
					$mpdconf .=<<<EOD
1663
	set auth enable radius-acct
1664

    
1665
EOD;
1666
				}
1667
				if (!empty($pppoecfg['radius']['nasip'])) {
1668
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
1669
				}
1670
			}
1671

    
1672
			fwrite($fd, $mpdconf);
1673
			fclose($fd);
1674
			unset($mpdconf);
1675

    
1676
			if ($pppoecfg['username']) {
1677
				/* write mpd.secret */
1678
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1679
				if (!$fd) {
1680
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1681
					return 1;
1682
				}
1683

    
1684
				$mpdsecret = "\n\n";
1685

    
1686
				if (!empty($pppoecfg['username'])) {
1687
					$item = explode(" ", $pppoecfg['username']);
1688
					foreach ($item as $userdata) {
1689
						$data = explode(":", $userdata);
1690
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1691
					}
1692
				}
1693

    
1694
				fwrite($fd, $mpdsecret);
1695
				fclose($fd);
1696
				unset($mpdsecret);
1697
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1698
			}
1699

    
1700
			/* Check if previous instance is still up */
1701
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
1702
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1703
			}
1704

    
1705
			/* Get support for netgraph(4) from the nic */
1706
			pfSense_ngctl_attach(".", $pppoe_interface);
1707
			/* fire up mpd */
1708
			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");
1709

    
1710
			break;
1711
	}
1712

    
1713
	if (platform_booting()) {
1714
		echo gettext("done") . "\n";
1715
	}
1716

    
1717
	return 0;
1718
}
1719

    
1720
function vpn_l2tp_configure() {
1721
	global $config, $g;
1722

    
1723
	$syscfg = $config['system'];
1724
	$l2tpcfg = $config['l2tp'];
1725

    
1726
	/* create directory if it does not exist */
1727
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
1728
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1729
	}
1730

    
1731
	if (platform_booting()) {
1732
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
1733
			return 0;
1734
		}
1735

    
1736
		echo gettext("Configuring l2tp VPN service... ");
1737
	} else {
1738
		/* kill mpd */
1739
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1740

    
1741
		/* wait for process to die */
1742
		sleep(8);
1743

    
1744
	}
1745

    
1746
	/* make sure l2tp-vpn directory exists */
1747
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn")) {
1748
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1749
	}
1750

    
1751
	switch ($l2tpcfg['mode']) {
1752

    
1753
		case 'server':
1754
			$l2tp_listen="";
1755
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
1756
			if (is_ipaddrv4($ipaddr)) {
1757
				$l2tp_listen="set l2tp self $ipaddr";
1758
			}
1759

    
1760
			switch ($l2tpcfg['paporchap']) {
1761
				case 'chap':
1762
					$paporchap = "set link enable chap";
1763
					break;
1764
				case 'chap-msv2':
1765
					$paporchap = "set link enable chap-msv2";
1766
					break;
1767
				default:
1768
					$paporchap = "set link enable pap";
1769
					break;
1770
			}
1771

    
1772
			/* write mpd.conf */
1773
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1774
			if (!$fd) {
1775
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1776
				return 1;
1777
			}
1778

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

    
1781
			$issue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 ";
1782
			if (isset($l2tpcfg['radius']['radiusissueips']) && isset($l2tpcfg['radius']['server']['enable'])) {
1783
				$issue_ip_type .= "0.0.0.0/0";
1784
			} else {
1785
				$issue_ip_type .= "ippool p0";
1786
			}
1787

    
1788
			$ipcp_nbns = '';
1789
			if (is_ipaddr($l2tpcfg['wins'])) {
1790
				$ipcp_nbns = "set ipcp nbns {$l2tpcfg['wins']}";
1791
			}
1792

    
1793
			$ipcp_dns = '';
1794
			if (is_ipaddr($l2tpcfg['dns1'])) {
1795
				$ipcp_dns = "set ipcp dns " . $l2tpcfg['dns1'];
1796
				if (is_ipaddr($l2tpcfg['dns2'])) {
1797
					$ipcp_dns .= " " . $l2tpcfg['dns2'];
1798
				}
1799
			} elseif (isset ($config['dnsmasq']['enable']) ||
1800
			    isset ($config['unbound']['enable'])) {
1801
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1802
				if ($syscfg['dnsserver'][0]) {
1803
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1804
				}
1805
			} elseif (is_array($syscfg['dnsserver']) &&
1806
			    ($syscfg['dnsserver'][0])) {
1807
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1808
			}
1809

    
1810
			$mpdconf =<<<EOD
1811

    
1812
startup:
1813

    
1814
l2tps:
1815
	set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}
1816

    
1817
	create bundle template l2tp_b
1818
	set bundle enable compression
1819
	set bundle yes crypt-reqd
1820

    
1821
	set ccp yes mppc
1822

    
1823
	set iface group l2tp
1824
	set iface up-script /usr/local/sbin/vpn-linkup
1825
	set iface down-script /usr/local/sbin/vpn-linkdown
1826
	set iface disable on-demand
1827
	set iface enable proxy-arp
1828

    
1829
	set ipcp yes vjcomp
1830
	{$issue_ip_type}
1831
	{$ipcp_nbns}
1832
	{$ipcp_dns}
1833

    
1834
	create link template l2tp_l l2tp
1835
	set link action bundle l2tp_b
1836

    
1837
	set link yes acfcomp protocomp
1838
	set link enable multilink
1839
	set link no pap chap chap-msv2
1840
	{$paporchap}
1841
	{$l2tp_listen}
1842
	set link keep-alive 10 180
1843
	set link enable incoming
1844

    
1845
EOD;
1846

    
1847

    
1848
			if (isset ($l2tpcfg['radius']['enable'])) {
1849
				$mpdconf .=<<<EOD
1850
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1851
	set radius retries 3
1852
	set radius timeout 10
1853
	set auth enable radius-auth
1854

    
1855
EOD;
1856

    
1857
				if (isset ($l2tpcfg['radius']['accounting'])) {
1858
					$mpdconf .=<<<EOD
1859
	set auth enable radius-acct
1860

    
1861
EOD;
1862
				}
1863
			}
1864

    
1865
			fwrite($fd, $mpdconf);
1866
			fclose($fd);
1867
			unset($mpdconf);
1868

    
1869
			/* write mpd.secret */
1870
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1871
			if (!$fd) {
1872
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1873
				return 1;
1874
			}
1875

    
1876
			$mpdsecret = "\n\n";
1877

    
1878
			if (is_array($l2tpcfg['user'])) {
1879
				foreach ($l2tpcfg['user'] as $user) {
1880
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1881
				}
1882
			}
1883

    
1884
			fwrite($fd, $mpdsecret);
1885
			fclose($fd);
1886
			unset($mpdsecret);
1887
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1888

    
1889
			vpn_netgraph_support();
1890

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

    
1894
			break;
1895

    
1896
		case 'redir':
1897
			break;
1898
	}
1899

    
1900
	if (platform_booting()) {
1901
		echo "done\n";
1902
	}
1903

    
1904
	return 0;
1905
}
1906

    
1907
?>
(45-45/51)