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
	foreach (array_keys($ipsec_log_cats) as $cat) {
51
		if (is_numeric($config['ipsec']['logging'][$cat]) &&
52
		    in_array(intval($config['ipsec']['logging'][$cat]), array_keys($ipsec_log_sevs), true)) {
53
			$cfgtext[] = "${cat} = {$config['ipsec']['logging'][$cat]}";
54
		}
55
	}
56

    
57
	return $cfgtext;
58
}
59

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

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

    
118
	return $conversion;
119
}
120

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

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

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

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

    
134
	$syscfg = $config['system'];
135
	$ipseccfg = $config['ipsec'];
136
	if (!ipsec_enabled()) {
137
		/* try to stop charon */
138
		mwexec("/usr/local/sbin/ipsec stop");
139
		/* Stop dynamic monitoring */
140
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
141

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
413
	unset($stronconf);
414

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

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

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

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

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

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

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

    
470
EOD;
471

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

    
487
EOD;
488
		}
489
	}
490

    
491
	/* write an eap-radius config section if appropriate */
492
	if (strlen($radius_server_txt) && ($mobile_ipsec_auth === "eap-radius")) {
493
		$strongswan .= <<<EOD
494
		eap-radius {
495
			class_group = yes
496
			eap_start = no
497
			servers {
498
{$radius_server_txt}
499
			}
500
		}
501

    
502
EOD;
503
	}
504

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
630
	$pskconf = "";
631

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

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

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

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

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

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

    
662
				@chmod($certpath, 0600);
663

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

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

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

    
685
				$myid = trim($myid_data);
686

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
813
EOD;
814
				}
815
			}
816
		}
817

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1009
				}
1010
			}
1011

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

    
1096
			$left_spec = $ep;
1097

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

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

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

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

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

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

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

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

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

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

    
1185
						$leftsubnet_spec[] = $leftsubnet_data;
1186

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

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

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

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

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

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

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

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

    
1295
				}
1296
			}
1297

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

    
1314
EOD;
1315

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1545
	}
1546

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

    
1549
		case 'server':
1550

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

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

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

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

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

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

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

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

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

    
1604
	create bundle template poes_b
1605
	set bundle enable compression
1606

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

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

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

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

    
1628
	set auth max-logins {$pppoemaxlogins}
1629

    
1630
	set pppoe iface {$pppoe_interface}
1631

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

    
1641
EOD;
1642

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

    
1658
EOD;
1659

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

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

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

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

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

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

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

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

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

    
1709
			break;
1710
	}
1711

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

    
1716
	return 0;
1717
}
1718

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

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

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

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

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

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

    
1743
	}
1744

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

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

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

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

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

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

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

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

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

    
1809
			$mpdconf =<<<EOD
1810

    
1811
startup:
1812

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

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

    
1820
	set ccp yes mppc
1821

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

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

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

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

    
1844
EOD;
1845

    
1846

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

    
1854
EOD;
1855

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

    
1860
EOD;
1861
				}
1862
			}
1863

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

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

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

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

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

    
1888
			vpn_netgraph_support();
1889

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

    
1893
			break;
1894

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

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

    
1903
	return 0;
1904
}
1905

    
1906
?>
(45-45/51)