Project

General

Profile

Download (54.8 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
	/* Activate RADIUS accounting if it was selected on the auth server view */
493
	$radius_accounting = "";
494
	if($auth_server && isset($auth_server['radius_acct_port'])){
495
		$radius_accounting = 'accounting = yes';
496
	}
497

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

    
510
EOD;
511
	}
512

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
638
	$pskconf = "";
639

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

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

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

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

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

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

    
670
				@chmod($certpath, 0600);
671

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

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

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

    
693
				$myid = trim($myid_data);
694

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
821
EOD;
822
				}
823
			}
824
		}
825

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

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

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

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

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

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

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

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

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

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

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

    
969
				$ealgosp1 .= "!";
970
			}
971

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

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

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

    
1007
			if (!empty($ph1ent['caref'])) {
1008
				$ca = lookup_ca($ph1ent['caref']);
1009
				if ($ca) {
1010
					$casubarr = cert_get_subject_array($ca['crt']);
1011
					$casub = "";
1012
					foreach ($casubarr as $casubfield) {
1013
						if (empty($casub)) {
1014
							$casub = "/";
1015
						}
1016
						$casub .= "{$casubfield['a']}={$casubfield['v']}/";
1017
					}
1018

    
1019
				}
1020
			}
1021

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

    
1106
			$left_spec = $ep;
1107

    
1108
			if (isset($ph1ent['reauth_enable'])) {
1109
				$reauth = "reauth = no";
1110
			} else {
1111
				$reauth = "reauth = yes";
1112
			}
1113

    
1114
			if (isset($ph1ent['rekey_enable'])) {
1115
				$rekeyline = "rekey = no";
1116
			} else {
1117
				$rekeyline = "rekey = yes";
1118
				if(!empty($ph1ent['margintime'])){
1119
					$rekeyline .= "\n\tmargintime = {$ph1ent['margintime']}s";
1120
				}
1121
			}
1122

    
1123
			if ($ph1ent['nat_traversal'] == 'off') {
1124
				$forceencaps = 'forceencaps = no';
1125
			} else if ($ph1ent['nat_traversal'] == 'force') {
1126
				$forceencaps = 'forceencaps = yes';
1127
			} else {
1128
				$forceencaps = 'forceencaps = no';
1129
			}
1130

    
1131
			if ($ph1ent['mobike'] == 'on') {
1132
				$mobike = 'mobike = yes';
1133
			} else {
1134
				$mobike = 'mobike = no';
1135
			}
1136

    
1137
			if (isset($ph1ent['tfc_enable'])) {
1138
				if (isset($ph1ent['tfc_bytes']) && is_numericint($ph1ent['tfc_bytes'])) {
1139
					$tfc = "tfc = {$ph1ent['tfc_bytes']}";
1140
				} else {
1141
					$tfc = "tfc = %mtu";
1142
				}
1143
			}
1144

    
1145
			$ipseclifetime = 0;
1146
			$rightsubnet_spec = array();
1147
			$leftsubnet_spec = array();
1148
			$reqids = array();
1149
			$ealgoAHsp2arr = array();
1150
			$ealgoESPsp2arr = array();
1151
			if (is_array($a_phase2) && count($a_phase2)) {
1152
				foreach ($a_phase2 as $ph2ent) {
1153
					if ($ikeid != $ph2ent['ikeid']) {
1154
						continue;
1155
					}
1156

    
1157
					if (isset($ph2ent['disabled'])) {
1158
						continue;
1159
					}
1160

    
1161
					if (isset($ph2ent['mobile']) && !isset($a_client['enable'])) {
1162
						continue;
1163
					}
1164

    
1165
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
1166
						$tunneltype = "type = tunnel";
1167

    
1168
						$localid_type = $ph2ent['localid']['type'];
1169
						$leftsubnet_data = ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode']);
1170

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

    
1199
						$leftsubnet_spec[] = $leftsubnet_data;
1200

    
1201
						if (!isset($ph2ent['mobile'])) {
1202
							$tmpsubnet = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
1203
							$rightsubnet_spec[] = $tmpsubnet;
1204
						} else if (!empty($a_client['pool_address'])) {
1205
							$rightsubnet_spec[] = "{$a_client['pool_address']}/{$a_client['pool_netbits']}";
1206
						}
1207
					} else {
1208
						$tunneltype = "type = transport";
1209

    
1210
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
1211
						    ($ph1ent['authentication_method'] == "pre_shared_key")) &&
1212
						    isset($ph1ent['mobile'])) {
1213
							$left_spec = "%any";
1214
						} else {
1215
							$tmpsubnet = ipsec_get_phase1_src($ph1ent);
1216
							$leftsubnet_spec[] = $tmpsubnet;
1217
						}
1218

    
1219
						if (!isset($ph2ent['mobile'])) {
1220
							$rightsubnet_spec[] = $right_spec;
1221
						}
1222
					}
1223

    
1224
					if (isset($a_client['pfs_group']) && isset($ph2ent['mobile'])) {
1225
						$ph2ent['pfsgroup'] = $a_client['pfs_group'];
1226
					}
1227

    
1228
					if ($ph2ent['protocol'] == 'esp') {
1229
						if (is_array($ph2ent['encryption-algorithm-option'])) {
1230
							foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
1231
								$ealg_id = $ealg['name'];
1232
								$ealg_kl = $ealg['keylen'];
1233

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

    
1301
					$reqids[] = $ph2ent['reqid'];
1302

    
1303
					if (!empty($ph2ent['lifetime'])) {
1304
						if ($ipseclifetime == 0 || intval($ipseclifetime) > intval($ph2ent['lifetime'])) {
1305
							$ipseclifetime = intval($ph2ent['lifetime']);
1306
						}
1307
					}
1308

    
1309
				}
1310
			}
1311

    
1312
			$ipsecconnect =<<<EOD
1313
	fragmentation = yes
1314
	keyexchange = {$keyexchange}
1315
	{$reauth}
1316
	{$forceencaps}
1317
	{$mobike}
1318
	{$tfc}
1319
	{$rekeyline}
1320
	installpolicy = yes
1321
	{$tunneltype}
1322
	{$dpdline}
1323
	auto = {$passive}
1324
	left = {$left_spec}
1325
	right = {$right_spec}
1326
	{$leftid}
1327

    
1328
EOD;
1329

    
1330
			/* Disable ipcomp for now. redmine #6167
1331
			if (isset($config['ipsec']['compression'])) {
1332
				$ipsecconnect .= "\tcompress = yes\n";
1333
				$enablecompression = true;
1334
			} */
1335
			if (!empty($ikelifeline)) {
1336
				$ipsecconnect .= "\t{$ikelifeline}\n";
1337
			}
1338
			if ($ipseclifetime > 0) {
1339
				$ipsecconnect .= "\tlifetime = {$ipseclifetime}s\n";
1340
			}
1341
			if (!empty($rightsourceip)) {
1342
				$ipsecconnect .= "{$rightsourceip}";
1343
			}
1344
			if (!empty($ealgosp1)) {
1345
				$ipsecconnect .= "\t{$ealgosp1}\n";
1346
			}
1347
			if (!empty($ealgoAHsp2arr)) {
1348
				$ipsecconnect .= "\tah = " . join(',', $ealgoAHsp2arr) . "!\n";
1349
			}
1350
			if (!empty($ealgoESPsp2arr)) {
1351
				$ipsecconnect .= "\tesp = " . join(',', $ealgoESPsp2arr) . "!\n";
1352
			}
1353
			if (!empty($authentication)) {
1354
				$ipsecconnect .= "\t{$authentication}\n";
1355
			}
1356
			if (!empty($peerid_spec)) {
1357
				$ipsecconnect .= "\trightid = {$peerid_spec}\n";
1358
			}
1359
			if ($keyexchange != 'ikev2') {
1360
				$ipsecconnect .= "\taggressive = {$aggressive}\n";
1361
			}
1362

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

    
1406
	@file_put_contents("{$g['varetc_path']}/ipsec/ipsec.conf", $ipsecconf);
1407
	unset($ipsecconf);
1408
	/* end ipsec.conf */
1409

    
1410
	if ($enablecompression === true) {
1411
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 1);
1412
	} else {
1413
		set_single_sysctl('net.inet.ipcomp.ipcomp_enable', 0);
1414
	}
1415

    
1416
	/* manage process */
1417
	if ($restart === true) {
1418
		mwexec("/usr/local/sbin/ipsec restart", false);
1419
	} else {
1420
		if (isvalidpid("{$g['varrun_path']}/starter.charon.pid")) {
1421
			/* Update configuration changes */
1422
			/* Read secrets */
1423
			mwexec("/usr/local/sbin/ipsec rereadall", false);
1424
			mwexec("/usr/local/sbin/ipsec reload", false);
1425
		} else {
1426
			mwexec("/usr/local/sbin/ipsec start", false);
1427
		}
1428
	}
1429

    
1430
	// run ping_hosts.sh once if it's enabled to avoid wait for minicron
1431
	if ($ipsecpinghostsactive == true) {
1432
		mwexec_bg("/usr/local/bin/ping_hosts.sh");
1433
	}
1434

    
1435
	if ($natfilterrules == true) {
1436
		filter_configure();
1437
	}
1438
	/* start filterdns, if necessary */
1439
	if (count($filterdns_list) > 0) {
1440
		$interval = 60;
1441
		if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval'])) {
1442
			$interval = $ipseccfg['dns-interval'];
1443
		}
1444

    
1445
		$hostnames = "";
1446
		array_unique($filterdns_list);
1447
		foreach ($filterdns_list as $hostname) {
1448
			$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
1449
		}
1450
		file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
1451
		unset($hostnames);
1452

    
1453
		if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid")) {
1454
			sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
1455
		} else {
1456
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
1457
		}
1458
	} else {
1459
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
1460
		@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
1461
	}
1462

    
1463
	if (platform_booting()) {
1464
		echo "done\n";
1465
	}
1466

    
1467
	unlock($ipsecstartlock);
1468
	return count($filterdns_list);
1469
}
1470

    
1471
/*
1472
 * Forcefully restart IPsec
1473
 * This is required for when dynamic interfaces reload
1474
 * For all other occasions the normal vpn_ipsec_configure()
1475
 * will gracefully reload the settings without restarting
1476
 */
1477
function vpn_ipsec_force_reload($interface = "") {
1478
	global $g, $config;
1479

    
1480
	if (!ipsec_enabled()) {
1481
		return;
1482
	}
1483

    
1484
	$ipseccfg = $config['ipsec'];
1485

    
1486
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1487
		$found = false;
1488
		foreach ($ipseccfg['phase1'] as $ipsec) {
1489
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1490
				$found = true;
1491
				break;
1492
			}
1493
		}
1494
		if (!$found) {
1495
			log_error(sprintf(gettext("Ignoring IPsec reload since there are no tunnels on interface %s"), $interface));
1496
			return;
1497
		}
1498
	}
1499

    
1500
	/* If we get this far then we need to take action. */
1501
	log_error(gettext("Forcefully reloading IPsec"));
1502
	vpn_ipsec_configure();
1503
}
1504

    
1505
/* master setup for vpn (mpd) */
1506
function vpn_setup() {
1507
	/* start pppoe server */
1508
	vpn_pppoes_configure();
1509

    
1510
	/* setup l2tp */
1511
	vpn_l2tp_configure();
1512
}
1513

    
1514
function vpn_netgraph_support() {
1515
	$iflist = get_configured_interface_list();
1516
	foreach ($iflist as $iface) {
1517
		$realif = get_real_interface($iface);
1518
		/* Get support for netgraph(4) from the nic */
1519
		$ifinfo = pfSense_get_interface_addresses($realif);
1520
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge"))) {
1521
			pfSense_ngctl_attach(".", $realif);
1522
		}
1523
	}
1524
}
1525

    
1526
function vpn_pppoes_configure() {
1527
	global $config;
1528

    
1529
	if (is_array($config['pppoes']['pppoe'])) {
1530
		foreach ($config['pppoes']['pppoe'] as $pppoe) {
1531
			vpn_pppoe_configure($pppoe);
1532
		}
1533
	}
1534
}
1535

    
1536
function vpn_pppoe_configure(&$pppoecfg) {
1537
	global $config, $g;
1538

    
1539
	$syscfg = $config['system'];
1540

    
1541
	/* create directory if it does not exist */
1542
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn")) {
1543
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1544
	}
1545

    
1546
	if (platform_booting()) {
1547
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off")) {
1548
			return 0;
1549
		}
1550

    
1551
		echo gettext("Configuring PPPoE Server service... ");
1552
	} else {
1553
		/* kill mpd */
1554
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1555

    
1556
		/* wait for process to die */
1557
		sleep(2);
1558

    
1559
	}
1560

    
1561
	switch ($pppoecfg['mode']) {
1562

    
1563
		case 'server':
1564

    
1565
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1566

    
1567
			if ($pppoecfg['paporchap'] == "chap") {
1568
				$paporchap = "set link enable chap";
1569
			} else {
1570
				$paporchap = "set link enable pap";
1571
			}
1572

    
1573
			/* write mpd.conf */
1574
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1575
			if (!$fd) {
1576
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1577
				return 1;
1578
			}
1579

    
1580
			$issue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 ";
1581
			if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1582
				$issue_ip_type .= "0.0.0.0/0";
1583
			} else {
1584
				$issue_ip_type .= "ippool p0";
1585
			}
1586

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

    
1589
			if (is_numeric($pppoecfg['n_pppoe_maxlogin']) && ($pppoecfg['n_pppoe_maxlogin'] > 0)) {
1590
				$pppoemaxlogins = $pppoecfg['n_pppoe_maxlogin'];
1591
			} else {
1592
				$pppoemaxlogins = 1;
1593
			}
1594

    
1595
			$ipcp_dns = '';
1596
			if (!empty($pppoecfg['dns1'])) {
1597
				$ipcp_dns = "set ipcp dns " . $pppoecfg['dns1'];
1598
				if (!empty($pppoecfg['dns2'])) {
1599
					$ipcp_dns .= " " . $pppoecfg['dns2'];
1600
				}
1601
			} elseif (isset($config['dnsmasq']['enable']) ||
1602
			    isset ($config['unbound']['enable'])) {
1603
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1604
				if ($syscfg['dnsserver'][0]) {
1605
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1606
				}
1607
			} elseif (is_array($syscfg['dnsserver']) &&
1608
			    ($syscfg['dnsserver'][0])) {
1609
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1610
			}
1611

    
1612
			$mpdconf = <<<EOD
1613
startup:
1614

    
1615
poes:
1616
	set ippool add p0 {$pppoecfg['remoteip']} {$ippool_p0}
1617

    
1618
	create bundle template poes_b
1619
	set bundle enable compression
1620

    
1621
	set ccp yes mppc
1622
	set mppc yes e40
1623
	set mppc yes e128
1624
	set mppc yes stateless
1625

    
1626
	set iface group pppoe
1627
	set iface up-script /usr/local/sbin/vpn-linkup
1628
	set iface down-script /usr/local/sbin/vpn-linkdown
1629
	set iface idle 0
1630
	set iface disable on-demand
1631
	set iface disable proxy-arp
1632
	set iface enable tcpmssfix
1633
	set iface mtu 1500
1634

    
1635
	set ipcp no vjcomp
1636
	{$issue_ip_type}
1637
	{$ipcp_dns}
1638

    
1639
	create link template poes_l pppoe
1640
	set link action bundle poes_b
1641

    
1642
	set auth max-logins {$pppoemaxlogins}
1643

    
1644
	set pppoe iface {$pppoe_interface}
1645

    
1646
	set link no multilink
1647
	set link no pap chap
1648
	{$paporchap}
1649
	set link keep-alive 60 180
1650
	set link max-redial -1
1651
	set link mru 1492
1652
	set link latency 1
1653
	set link enable incoming
1654

    
1655
EOD;
1656

    
1657
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1658
				$radiusport = "";
1659
				$radiusacctport = "";
1660
				if (isset($pppoecfg['radius']['server']['port'])) {
1661
					$radiusport = $pppoecfg['radius']['server']['port'];
1662
				}
1663
				if (isset($pppoecfg['radius']['server']['acctport'])) {
1664
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1665
				}
1666
				$mpdconf .=<<<EOD
1667
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1668
	set radius retries 3
1669
	set radius timeout 10
1670
	set auth enable radius-auth
1671

    
1672
EOD;
1673

    
1674
				if (isset ($pppoecfg['radius']['accounting'])) {
1675
					$mpdconf .=<<<EOD
1676
	set auth enable radius-acct
1677

    
1678
EOD;
1679
				}
1680
				if (!empty($pppoecfg['radius']['nasip'])) {
1681
					$mpdconf .= "\tset radius me {$pppoecfg['radius']['nasip']}\n";
1682
				}
1683
			}
1684

    
1685
			fwrite($fd, $mpdconf);
1686
			fclose($fd);
1687
			unset($mpdconf);
1688

    
1689
			if ($pppoecfg['username']) {
1690
				/* write mpd.secret */
1691
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1692
				if (!$fd) {
1693
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1694
					return 1;
1695
				}
1696

    
1697
				$mpdsecret = "\n\n";
1698

    
1699
				if (!empty($pppoecfg['username'])) {
1700
					$item = explode(" ", $pppoecfg['username']);
1701
					foreach ($item as $userdata) {
1702
						$data = explode(":", $userdata);
1703
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1704
					}
1705
				}
1706

    
1707
				fwrite($fd, $mpdsecret);
1708
				fclose($fd);
1709
				unset($mpdsecret);
1710
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1711
			}
1712

    
1713
			/* Check if previous instance is still up */
1714
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid")) {
1715
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1716
			}
1717

    
1718
			/* Get support for netgraph(4) from the nic */
1719
			pfSense_ngctl_attach(".", $pppoe_interface);
1720
			/* fire up mpd */
1721
			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");
1722

    
1723
			break;
1724
	}
1725

    
1726
	if (platform_booting()) {
1727
		echo gettext("done") . "\n";
1728
	}
1729

    
1730
	return 0;
1731
}
1732

    
1733
function vpn_l2tp_configure() {
1734
	global $config, $g;
1735

    
1736
	$syscfg = $config['system'];
1737
	$l2tpcfg = $config['l2tp'];
1738

    
1739
	/* create directory if it does not exist */
1740
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn")) {
1741
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1742
	}
1743

    
1744
	if (platform_booting()) {
1745
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off")) {
1746
			return 0;
1747
		}
1748

    
1749
		echo gettext("Configuring l2tp VPN service... ");
1750
	} else {
1751
		/* kill mpd */
1752
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1753

    
1754
		/* wait for process to die */
1755
		sleep(8);
1756

    
1757
	}
1758

    
1759
	/* make sure l2tp-vpn directory exists */
1760
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn")) {
1761
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1762
	}
1763

    
1764
	switch ($l2tpcfg['mode']) {
1765

    
1766
		case 'server':
1767
			$l2tp_listen="";
1768
			$ipaddr = get_interface_ip(get_failover_interface($l2tpcfg['interface']));
1769
			if (is_ipaddrv4($ipaddr)) {
1770
				$l2tp_listen="set l2tp self $ipaddr";
1771
			}
1772

    
1773
			switch ($l2tpcfg['paporchap']) {
1774
				case 'chap':
1775
					$paporchap = "set link enable chap";
1776
					break;
1777
				case 'chap-msv2':
1778
					$paporchap = "set link enable chap-msv2";
1779
					break;
1780
				default:
1781
					$paporchap = "set link enable pap";
1782
					break;
1783
			}
1784

    
1785
			/* write mpd.conf */
1786
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1787
			if (!$fd) {
1788
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1789
				return 1;
1790
			}
1791

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

    
1794
			$issue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 ";
1795
			if (isset($l2tpcfg['radius']['radiusissueips']) && isset($l2tpcfg['radius']['server']['enable'])) {
1796
				$issue_ip_type .= "0.0.0.0/0";
1797
			} else {
1798
				$issue_ip_type .= "ippool p0";
1799
			}
1800

    
1801
			$ipcp_dns = '';
1802
			if (is_ipaddr($l2tpcfg['dns1'])) {
1803
				$ipcp_dns = "set ipcp dns " . $l2tpcfg['dns1'];
1804
				if (is_ipaddr($l2tpcfg['dns2'])) {
1805
					$ipcp_dns .= " " . $l2tpcfg['dns2'];
1806
				}
1807
			} elseif (isset ($config['dnsmasq']['enable']) ||
1808
			    isset ($config['unbound']['enable'])) {
1809
				$ipcp_dns = "set ipcp dns " . get_interface_ip("lan");
1810
				if ($syscfg['dnsserver'][0]) {
1811
					$ipcp_dns .= " " . $syscfg['dnsserver'][0];
1812
				}
1813
			} elseif (is_array($syscfg['dnsserver']) &&
1814
			    ($syscfg['dnsserver'][0])) {
1815
				$ipcp_dns = "set ipcp dns " . join(" ", $syscfg['dnsserver']);
1816
			}
1817

    
1818
			$mpdconf =<<<EOD
1819

    
1820
startup:
1821

    
1822
l2tps:
1823
	set ippool add p0 {$l2tpcfg['remoteip']} {$ippool_p0}
1824

    
1825
	create bundle template l2tp_b
1826
	set bundle enable compression
1827
	set bundle yes crypt-reqd
1828

    
1829
	set ccp yes mppc
1830

    
1831
	set iface group l2tp
1832
	set iface up-script /usr/local/sbin/vpn-linkup
1833
	set iface down-script /usr/local/sbin/vpn-linkdown
1834
	set iface disable on-demand
1835
	set iface enable proxy-arp
1836

    
1837
	set ipcp yes vjcomp
1838
	{$issue_ip_type}
1839
	{$ipcp_dns}
1840

    
1841
	create link template l2tp_l l2tp
1842
	set link action bundle l2tp_b
1843

    
1844
	set link yes acfcomp protocomp
1845
	set link enable multilink
1846
	set link no pap chap chap-msv2
1847
	{$paporchap}
1848
	{$l2tp_listen}
1849
	set link keep-alive 10 180
1850
	set link enable incoming
1851

    
1852
EOD;
1853

    
1854

    
1855
			if (isset ($l2tpcfg['radius']['enable'])) {
1856
				$mpdconf .=<<<EOD
1857
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1858
	set radius retries 3
1859
	set radius timeout 10
1860
	set auth disable internal
1861
	set auth enable radius-auth
1862

    
1863
EOD;
1864

    
1865
				if (isset ($l2tpcfg['radius']['accounting'])) {
1866
					$mpdconf .=<<<EOD
1867
	set auth enable radius-acct
1868

    
1869
EOD;
1870
				}
1871
			}
1872

    
1873
			fwrite($fd, $mpdconf);
1874
			fclose($fd);
1875
			unset($mpdconf);
1876

    
1877
			/* write mpd.secret */
1878
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1879
			if (!$fd) {
1880
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1881
				return 1;
1882
			}
1883

    
1884
			$mpdsecret = "\n\n";
1885

    
1886
			if (is_array($l2tpcfg['user'])) {
1887
				foreach ($l2tpcfg['user'] as $user) {
1888
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1889
				}
1890
			}
1891

    
1892
			fwrite($fd, $mpdsecret);
1893
			fclose($fd);
1894
			unset($mpdsecret);
1895
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1896

    
1897
			vpn_netgraph_support();
1898

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

    
1902
			break;
1903

    
1904
		case 'redir':
1905
			break;
1906
	}
1907

    
1908
	if (platform_booting()) {
1909
		echo "done\n";
1910
	}
1911

    
1912
	return 0;
1913
}
1914

    
1915
?>
(48-48/54)