Project

General

Profile

Bug #8543 ยป vpn_ipsec_phase1.php

the changed working file - Thomas Eckardt, 05/28/2018 11:55 PM

 
1
<?php
2
/*
3
 * vpn_ipsec_phase1.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2018 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2008 Shrew Soft Inc
8
 * All rights reserved.
9
 *
10
 * originally based on 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
##|+PRIV
28
##|*IDENT=page-vpn-ipsec-editphase1
29
##|*NAME=VPN: IPsec: Edit Phase 1
30
##|*DESCR=Allow access to the 'VPN: IPsec: Edit Phase 1' page.
31
##|*MATCH=vpn_ipsec_phase1.php*
32
##|-PRIV
33

    
34
require_once("functions.inc");
35
require_once("guiconfig.inc");
36
require_once("ipsec.inc");
37
require_once("vpn.inc");
38
require_once("filter.inc");
39

    
40
if (!is_array($config['ipsec']['phase1'])) {
41
	$config['ipsec']['phase1'] = array();
42
}
43

    
44
if (!is_array($config['ipsec']['phase2'])) {
45
	$config['ipsec']['phase2'] = array();
46
}
47

    
48
$a_phase1 = &$config['ipsec']['phase1'];
49
$a_phase2 = &$config['ipsec']['phase2'];
50

    
51
if (is_numericint($_REQUEST['p1index'])) {
52
	$p1index = $_REQUEST['p1index'];
53
}
54

    
55
if (is_numericint($_REQUEST['dup'])) {
56
	$p1index = $_REQUEST['dup'];
57
}
58

    
59
if (isset($p1index) && $a_phase1[$p1index]) {
60
	// don't copy the ikeid on dup
61
	if (!isset($_REQUEST['dup']) || !is_numericint($_REQUEST['dup'])) {
62
		$pconfig['ikeid'] = $a_phase1[$p1index]['ikeid'];
63
	}
64

    
65
	$old_ph1ent = $a_phase1[$p1index];
66

    
67
	$pconfig['disabled'] = isset($a_phase1[$p1index]['disabled']);
68

    
69
	if ($a_phase1[$p1index]['interface']) {
70
		$pconfig['interface'] = $a_phase1[$p1index]['interface'];
71
	} else {
72
		$pconfig['interface'] = "wan";
73
	}
74

    
75
	list($pconfig['remotenet'], $pconfig['remotebits']) = explode("/", $a_phase1[$p1index]['remote-subnet']);
76

    
77
	if (isset($a_phase1[$p1index]['mobile'])) {
78
		$pconfig['mobile'] = 'true';
79
	} else {
80
		$pconfig['remotegw'] = $a_phase1[$p1index]['remote-gateway'];
81
	}
82

    
83
	if (empty($a_phase1[$p1index]['iketype'])) {
84
		$pconfig['iketype'] = "ikev1";
85
	} else {
86
		$pconfig['iketype'] = $a_phase1[$p1index]['iketype'];
87
	}
88
	$pconfig['mode'] = $a_phase1[$p1index]['mode'];
89
	$pconfig['protocol'] = $a_phase1[$p1index]['protocol'];
90
	$pconfig['myid_type'] = $a_phase1[$p1index]['myid_type'];
91
	$pconfig['myid_data'] = $a_phase1[$p1index]['myid_data'];
92
	$pconfig['peerid_type'] = $a_phase1[$p1index]['peerid_type'];
93
	$pconfig['peerid_data'] = $a_phase1[$p1index]['peerid_data'];
94
	$pconfig['encryption'] = $a_phase1[$p1index]['encryption'];
95
	$pconfig['lifetime'] = $a_phase1[$p1index]['lifetime'];
96
	$pconfig['authentication_method'] = $a_phase1[$p1index]['authentication_method'];
97

    
98
	if (($pconfig['authentication_method'] == "pre_shared_key") ||
99
	    ($pconfig['authentication_method'] == "xauth_psk_server")) {
100
		$pconfig['pskey'] = $a_phase1[$p1index]['pre-shared-key'];
101
	} else {
102
		$pconfig['certref'] = $a_phase1[$p1index]['certref'];
103
		$pconfig['caref'] = $a_phase1[$p1index]['caref'];
104
	}
105

    
106
	$pconfig['descr'] = $a_phase1[$p1index]['descr'];
107
	$pconfig['nat_traversal'] = $a_phase1[$p1index]['nat_traversal'];
108
	$pconfig['mobike'] = $a_phase1[$p1index]['mobike'];
109

    
110
	if (isset($a_phase1[$p1index]['reauth_enable'])) {
111
		$pconfig['reauth_enable'] = true;
112
	}
113

    
114
	if (isset($a_phase1[$p1index]['rekey_enable'])) {
115
		$pconfig['rekey_enable'] = true;
116
	}
117

    
118
	if ($a_phase1[$p1index]['margintime']) {
119
		$pconfig['margintime'] = $a_phase1[$p1index]['margintime'];
120
	}
121

    
122
	if (isset($a_phase1[$p1index]['responderonly'])) {
123
		$pconfig['responderonly'] = true;
124
	}
125

    
126
	if ($a_phase1[$p1index]['dpd_delay'] && $a_phase1[$p1index]['dpd_maxfail']) {
127
		$pconfig['dpd_enable'] = true;
128
		$pconfig['dpd_delay'] = $a_phase1[$p1index]['dpd_delay'];
129
		$pconfig['dpd_maxfail'] = $a_phase1[$p1index]['dpd_maxfail'];
130
	}
131

    
132
	if (isset($a_phase1[$p1index]['splitconn'])) {
133
		$pconfig['splitconn'] = true;
134
	}
135

    
136
	if (isset($a_phase1[$p1index]['tfc_enable'])) {
137
		$pconfig['tfc_enable'] = true;
138
	}
139

    
140
	if (isset($a_phase1[$p1index]['tfc_bytes'])) {
141
		$pconfig['tfc_bytes'] = $a_phase1[$p1index]['tfc_bytes'];
142
	}
143
} else {
144
	/* defaults */
145
	$pconfig['interface'] = "wan";
146
	if ($config['interfaces']['lan']) {
147
		$pconfig['localnet'] = "lan";
148
	}
149
	$pconfig['mode'] = "main";
150
	$pconfig['protocol'] = "inet";
151
	$pconfig['myid_type'] = "myaddress";
152
	$pconfig['peerid_type'] = "peeraddress";
153
	$pconfig['authentication_method'] = "pre_shared_key";
154
	$pconfig['lifetime'] = "28800";
155
	$pconfig['rekey_enable'] = true;
156
	$pconfig['nat_traversal'] = 'on';
157
	$pconfig['mobike'] = 'off';
158
	$pconfig['dpd_enable'] = true;
159
	$pconfig['iketype'] = "ikev1";
160

    
161
	/* mobile client */
162
	if ($_REQUEST['mobile']) {
163
		$pconfig['mobile'] = true;
164
		$pconfig['mode'] = "aggressive";
165
	}
166
}
167
// default value for new P1 and failsafe to always have at least 1 encryption item for the Form_ListItem
168
if (!is_array($pconfig['encryption']['item']) || count($pconfig['encryption']['item']) == 0) {
169
	$item = array();
170
	$item['encryption-algorithm'] = array(name => "aes");
171
	$item['hash-algorithm'] = "sha1";
172
	$item['dhgroup'] = "2";
173
	$pconfig['encryption']['item'][] = $item;
174
}
175

    
176
if (isset($_REQUEST['dup']) && is_numericint($_REQUEST['dup'])) {
177
	unset($p1index);
178
}
179

    
180
if ($_POST['save']) {
181
	unset($input_errors);
182
	$pconfig = $_POST;
183

    
184
	for($i = 0; $i < 100; $i++) {
185
		if (isset($_POST['ealgo_algo'.$i])) {
186
			$item = array();
187
			$item['encryption-algorithm']['name'] = $_POST['ealgo_algo'.$i];
188
			$item['encryption-algorithm']['keylen'] = $_POST['ealgo_keylen'.$i];
189
//			$item['encryption-algorithm']['keylen'] = 256;
190
			$item['hash-algorithm'] = $_POST['halgo'.$i];
191
			$item['dhgroup'] = $_POST['dhgroup'.$i];
192
			$pconfig['encryption']['item'][] = $item;
193
		}
194
	}
195

    
196
	/* input validation */
197

    
198
	$method = $pconfig['authentication_method'];
199

    
200
	// Unset ca and cert if not required to avoid storing in config
201
	if ($method == "pre_shared_key" || $method == "xauth_psk_server") {
202
		unset($pconfig['certref']);
203
	}
204

    
205
	if ($method != "rsasig" && $method != "xauth_rsa_server" && $method != "eap-tls") {
206
		unset($pconfig['caref']);
207
	}
208

    
209
	// Only require PSK here for normal PSK tunnels (not mobile) or xauth.
210
	// For RSA methods, require the CA/Cert.
211
	switch ($method) {
212
		case 'eap-mschapv2':
213
			if ($pconfig['iketype'] != 'ikev2') {
214
				$input_errors[] = gettext("EAP-MSChapv2 can only be used with IKEv2 type VPNs.");
215
			}
216
			break;
217
		case "eap-tls":
218
			if ($pconfig['iketype'] != 'ikev2') {
219
				$input_errors[] = gettext("EAP-TLS can only be used with IKEv2 type VPNs.");
220
			}
221
			break;
222
		case "eap-radius":
223
			if ($pconfig['iketype'] != 'ikev2') {
224
				$input_errors[] = gettext("EAP-RADIUS can only be used with IKEv2 type VPNs.");
225
			}
226
			break;
227
		case "pre_shared_key":
228
			// If this is a mobile PSK tunnel the user PSKs go on
229
			//	  the PSK tab, not here, so skip the check.
230
			if ($pconfig['mobile']) {
231
				break;
232
			}
233
		case "xauth_psk_server":
234
			$reqdfields = explode(" ", "pskey");
235
			$reqdfieldsn = array(gettext("Pre-Shared Key"));
236
			$validate_pskey = true;
237
			break;
238
		case "xauth_rsa_server":
239
		case "rsasig":
240
			$reqdfields = explode(" ", "caref certref");
241
			$reqdfieldsn = array(gettext("Certificate Authority"), gettext("Certificate"));
242
			break;
243
		default:
244
			/* Other types do not use this validation mechanism. */
245
	}
246

    
247
	if (!$pconfig['mobile']) {
248
		$reqdfields[] = "remotegw";
249
		$reqdfieldsn[] = gettext("Remote gateway");
250
	}
251

    
252
	do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
253

    
254
	if (isset($validate_pskey) && isset($pconfig['pskey']) && !preg_match('/^[[:ascii:]]*$/', $pconfig['pskey'])) {
255
		unset($validate_pskey);
256
		$input_errors[] = gettext("Pre-Shared Key contains invalid characters.");
257
	}
258

    
259
	if (($pconfig['lifetime'] && !is_numericint($pconfig['lifetime']))) {
260
		$input_errors[] = gettext("The P1 lifetime must be an integer.");
261
	}
262

    
263
	if (!isset($pconfig['rekey_enable']) && $pconfig['margintime']) {
264
		if(!is_numericint($pconfig['margintime'])){
265
			 $input_errors[] = gettext("The margintime must be an integer.");
266
		} else if(intval($pconfig['margintime']) >= intval($pconfig['lifetime'])){
267
			 $input_errors[] = gettext("The margintime must be smaller than the P1 lifetime.");
268
		}
269
	}
270

    
271
	if ($pconfig['remotegw']) {
272
		if (!is_ipaddr($pconfig['remotegw']) && !is_domain($pconfig['remotegw'])) {
273
			$input_errors[] = gettext("A valid remote gateway address or host name must be specified.");
274
		} elseif (is_ipaddrv4($pconfig['remotegw']) && ($pconfig['protocol'] == "inet6")) {
275
			$input_errors[] = gettext("A valid remote gateway IPv4 address must be specified or protocol needs to be changed to IPv6");
276
		} elseif (is_ipaddrv6($pconfig['remotegw']) && ($pconfig['protocol'] == "inet")) {
277
			$input_errors[] = gettext("A valid remote gateway IPv6 address must be specified or protocol needs to be changed to IPv4");
278
		}
279
	}
280

    
281
	if ($pconfig['remotegw'] && is_ipaddr($pconfig['remotegw']) && !isset($pconfig['disabled'])) {
282
		$t = 0;
283
		foreach ($a_phase1 as $ph1tmp) {
284
			if ($p1index != $t) {
285
				$tremotegw = $pconfig['remotegw'];
286
				if (($ph1tmp['remote-gateway'] == $tremotegw) && !isset($ph1tmp['disabled'])) {
287
					$input_errors[] = sprintf(gettext('The remote gateway "%1$s" is already used by phase1 "%2$s".'), $tremotegw, $ph1tmp['descr']);
288
				}
289
			}
290
			$t++;
291
		}
292
	}
293

    
294
	if (($pconfig['iketype'] == "ikev1") && is_array($a_phase2) && (count($a_phase2))) {
295
		foreach ($a_phase2 as $phase2) {
296
			if ($phase2['ikeid'] == $pconfig['ikeid']) {
297
				if (($pconfig['protocol'] == "inet") && ($phase2['mode'] == "tunnel6")) {
298
					$input_errors[] = gettext("There is a Phase 2 using IPv6, cannot use IPv4.");
299
					break;
300
				}
301
				if (($pconfig['protocol'] == "inet6") && ($phase2['mode'] == "tunnel")) {
302
					$input_errors[] = gettext("There is a Phase 2 using IPv4, cannot use IPv6.");
303
					break;
304
				}
305
			}
306
		}
307
	}
308

    
309
	/* My identity */
310

    
311
	if ($pconfig['myid_type'] == "myaddress") {
312
		$pconfig['myid_data'] = "";
313
	}
314

    
315
	if ($pconfig['myid_type'] == "address" and $pconfig['myid_data'] == "") {
316
		$input_errors[] = gettext("Please enter an address for 'My Identifier'");
317
	}
318

    
319
	if ($pconfig['myid_type'] == "keyid tag" and $pconfig['myid_data'] == "") {
320
		$input_errors[] = gettext("Please enter a keyid tag for 'My Identifier'");
321
	}
322

    
323
	if ($pconfig['myid_type'] == "fqdn" and $pconfig['myid_data'] == "") {
324
		$input_errors[] = gettext("Please enter a fully qualified domain name for 'My Identifier'");
325
	}
326

    
327
	if ($pconfig['myid_type'] == "user_fqdn" and $pconfig['myid_data'] == "") {
328
		$input_errors[] = gettext("Please enter a user and fully qualified domain name for 'My Identifier'");
329
	}
330

    
331
	if ($pconfig['myid_type'] == "dyn_dns" and $pconfig['myid_data'] == "") {
332
		$input_errors[] = gettext("Please enter a dynamic domain name for 'My Identifier'");
333
	}
334

    
335
	if (($pconfig['myid_type'] == "address") && !is_ipaddr($pconfig['myid_data'])) {
336
		$input_errors[] = gettext("A valid IP address for 'My identifier' must be specified.");
337
	}
338

    
339
	if (($pconfig['myid_type'] == "fqdn") && !is_domain($pconfig['myid_data'])) {
340
		$input_errors[] = gettext("A valid domain name for 'My identifier' must be specified.");
341
	}
342

    
343
	if ($pconfig['myid_type'] == "fqdn") {
344
		if (is_domain($pconfig['myid_data']) == false) {
345
			$input_errors[] = gettext("A valid FQDN for 'My identifier' must be specified.");
346
		}
347
	}
348

    
349
	if ($pconfig['myid_type'] == "user_fqdn") {
350
		$user_fqdn = explode("@", $pconfig['myid_data']);
351
		if (is_domain($user_fqdn[1]) == false) {
352
			$input_errors[] = gettext("A valid User FQDN in the form of user@my.domain.com for 'My identifier' must be specified.");
353
		}
354
	}
355

    
356
	if ($pconfig['myid_type'] == "dyn_dns") {
357
		if (is_domain($pconfig['myid_data']) == false) {
358
			$input_errors[] = gettext("A valid Dynamic DNS address for 'My identifier' must be specified.");
359
		}
360
	}
361

    
362
	/* Peer identity */
363

    
364
	if ($pconfig['myid_type'] == "peeraddress") {
365
		$pconfig['peerid_data'] = "";
366
	}
367

    
368
	// Only enforce peer ID if we are not dealing with a pure-psk mobile config.
369
	if (!(($pconfig['authentication_method'] == "pre_shared_key") && ($pconfig['mobile']))) {
370
		if ($pconfig['peerid_type'] == "address" and $pconfig['peerid_data'] == "") {
371
			$input_errors[] = gettext("Please enter an address for 'Peer Identifier'");
372
		}
373

    
374
		if ($pconfig['peerid_type'] == "keyid tag" and $pconfig['peerid_data'] == "") {
375
			$input_errors[] = gettext("Please enter a keyid tag for 'Peer Identifier'");
376
		}
377

    
378
		if ($pconfig['peerid_type'] == "fqdn" and $pconfig['peerid_data'] == "") {
379
			$input_errors[] = gettext("Please enter a fully qualified domain name for 'Peer Identifier'");
380
		}
381

    
382
		if ($pconfig['peerid_type'] == "user_fqdn" and $pconfig['peerid_data'] == "") {
383
			$input_errors[] = gettext("Please enter a user and fully qualified domain name for 'Peer Identifier'");
384
		}
385

    
386
		if ((($pconfig['peerid_type'] == "address") && !is_ipaddr($pconfig['peerid_data']))) {
387
			$input_errors[] = gettext("A valid IP address for 'Peer identifier' must be specified.");
388
		}
389

    
390
		if ((($pconfig['peerid_type'] == "fqdn") && !is_domain($pconfig['peerid_data']))) {
391
			$input_errors[] = gettext("A valid domain name for 'Peer identifier' must be specified.");
392
		}
393

    
394
		if ($pconfig['peerid_type'] == "fqdn") {
395
			if (is_domain($pconfig['peerid_data']) == false) {
396
				$input_errors[] = gettext("A valid FQDN for 'Peer identifier' must be specified.");
397
			}
398
		}
399

    
400
		if ($pconfig['peerid_type'] == "user_fqdn") {
401
			$user_fqdn = explode("@", $pconfig['peerid_data']);
402
			if (is_domain($user_fqdn[1]) == false) {
403
				$input_errors[] = gettext("A valid User FQDN in the form of user@my.domain.com for 'Peer identifier' must be specified.");
404
			}
405
		}
406
	}
407

    
408
	if ($pconfig['dpd_enable']) {
409
		if (!is_numericint($pconfig['dpd_delay'])) {
410
			$input_errors[] = gettext("A numeric value must be specified for DPD delay.");
411
		}
412

    
413
		if (!is_numericint($pconfig['dpd_maxfail'])) {
414
			$input_errors[] = gettext("A numeric value must be specified for DPD retries.");
415
		}
416
	}
417

    
418
	if ($pconfig['tfc_bytes'] && !is_numericint($pconfig['tfc_bytes'])) {
419
		$input_errors[] = gettext("A numeric value must be specified for TFC bytes.");
420
	}
421

    
422
	if (!empty($pconfig['iketype']) && $pconfig['iketype'] != "ikev1" && $pconfig['iketype'] != "ikev2" && $pconfig['iketype'] != "auto") {
423
		$input_errors[] = gettext("Valid arguments for IKE type are v1, v2 or auto");
424
	}
425

    
426
	foreach($pconfig['encryption']['item'] as $p1algo) {
427
		if (preg_match("/aes\d+gcm/", $p1algo['encryption-algorithm']['name']) && $_POST['iketype'] != "ikev2") {
428
			$input_errors[] = gettext("Encryption Algorithm AES-GCM can only be used with IKEv2");
429
		}
430
	}
431
	/* auth backend for mobile eap-radius VPNs should be a RADIUS server */
432
	if (($pconfig['authentication_method'] == 'eap-radius') && $pconfig['mobile']) {
433
		if (!empty($config['ipsec']['client']['user_source'])) {
434
			$auth_server_list  = explode(',', $config['ipsec']['client']['user_source']);
435
			foreach ($auth_server_list as $auth_server_name) {
436
				$auth_server       = auth_get_authserver($auth_server_name);
437
				if (!is_array($auth_server) || ($auth_server['type'] != 'radius')) {
438
					$input_errors[] = gettext("A valid RADIUS server must be selected for user authentication on the Mobile Clients tab in order to set EAP-RADIUS as the authentication method.");
439
				}
440
			}
441
		}
442
	}
443

    
444
	if (!$input_errors) {
445
		$ph1ent['ikeid'] = $pconfig['ikeid'];
446
		$ph1ent['iketype'] = $pconfig['iketype'];
447
		if ($pconfig['iketype'] == 'ikev2') {
448
			unset($ph1ent['mode']);
449
		} else {
450
			$ph1ent['mode'] = $pconfig['mode'];
451
		}
452
		$ph1ent['disabled'] = $pconfig['disabled'] ? true : false;
453
		$ph1ent['interface'] = $pconfig['interface'];
454
		/* if the remote gateway changed and the interface is not WAN then remove route */
455
		/* the vpn_ipsec_configure() handles adding the route */
456
		if ($pconfig['interface'] <> "wan") {
457
			if ($old_ph1ent['remote-gateway'] <> $pconfig['remotegw']) {
458
				mwexec("/sbin/route delete -host {$old_ph1ent['remote-gateway']}");
459
			}
460
		}
461

    
462
		if ($pconfig['mobile']) {
463
			$ph1ent['mobile'] = true;
464
		} else {
465
			$ph1ent['remote-gateway'] = $pconfig['remotegw'];
466
		}
467

    
468
		$ph1ent['protocol'] = $pconfig['protocol'];
469

    
470
		$ph1ent['myid_type'] = $pconfig['myid_type'];
471
		$ph1ent['myid_data'] = $pconfig['myid_data'];
472
		$ph1ent['peerid_type'] = $pconfig['peerid_type'];
473
		$ph1ent['peerid_data'] = $pconfig['peerid_data'];
474

    
475
		$ph1ent['encryption'] = $pconfig['encryption'];
476
		$ph1ent['lifetime'] = $pconfig['lifetime'];
477
		$ph1ent['pre-shared-key'] = $pconfig['pskey'];
478
		$ph1ent['private-key'] = base64_encode($pconfig['privatekey']);
479
		$ph1ent['certref'] = $pconfig['certref'];
480
		$ph1ent['caref'] = $pconfig['caref'];
481
		$ph1ent['authentication_method'] = $pconfig['authentication_method'];
482
		$ph1ent['descr'] = $pconfig['descr'];
483
		$ph1ent['nat_traversal'] = $pconfig['nat_traversal'];
484
		$ph1ent['mobike'] = $pconfig['mobike'];
485

    
486
		if (isset($pconfig['reauth_enable'])) {
487
			$ph1ent['reauth_enable'] = true;
488
		} else {
489
			unset($ph1ent['reauth_enable']);
490
		}
491

    
492
		if (isset($pconfig['rekey_enable'])) {
493
			$ph1ent['rekey_enable'] = true;
494
		} else {
495
			unset($ph1ent['rekey_enable']);
496
		}
497

    
498
		if (!isset($pconfig['rekey_enable'])) {
499
			$ph1ent['margintime'] = $pconfig['margintime'];
500
		} else {
501
			unset($ph1ent['margintime']);
502
		}
503

    
504
		if (isset($pconfig['responderonly'])) {
505
			$ph1ent['responderonly'] = true;
506
		} else {
507
			unset($ph1ent['responderonly']);
508
		}
509

    
510
		if (isset($pconfig['dpd_enable'])) {
511
			$ph1ent['dpd_delay'] = $pconfig['dpd_delay'];
512
			$ph1ent['dpd_maxfail'] = $pconfig['dpd_maxfail'];
513
		}
514

    
515
		if (isset($pconfig['splitconn'])) {
516
			$ph1ent['splitconn'] = true;
517
		} else {
518
			unset($ph1ent['splitconn']);
519
		}
520

    
521
		if (isset($pconfig['tfc_enable'])) {
522
			$ph1ent['tfc_enable'] = true;
523
		}
524

    
525
		if (isset($pconfig['tfc_bytes'])) {
526
			$ph1ent['tfc_bytes'] = $pconfig['tfc_bytes'];
527
		}
528

    
529
		/* generate unique phase1 ikeid */
530
		if ($ph1ent['ikeid'] == 0) {
531
			$ph1ent['ikeid'] = ipsec_ikeid_next();
532
		}
533

    
534
		if (isset($p1index) && $a_phase1[$p1index]) {
535
			$a_phase1[$p1index] = $ph1ent;
536
		} else {
537
			$a_phase1[] = $ph1ent;
538
		}
539

    
540
		write_config(gettext("Saved IPsec tunnel Phase 1 configuration."));
541
		mark_subsystem_dirty('ipsec');
542

    
543
		header("Location: vpn_ipsec.php");
544
		exit;
545
	}
546
}
547

    
548
function build_interface_list() {
549
	$interfaces = get_configured_interface_with_descr();
550

    
551
	$viplist = get_configured_vip_list();
552
	foreach ($viplist as $vip => $address) {
553
		$interfaces[$vip] = $address;
554
		if (get_vip_descr($address)) {
555
			$interfaces[$vip] .= " (". get_vip_descr($address) .")";
556
		}
557
	}
558

    
559
	$grouplist = return_gateway_groups_array();
560

    
561
	foreach ($grouplist as $name => $group) {
562
		if ($group[0]['vip'] != "") {
563
			$vipif = $group[0]['vip'];
564
		} else {
565
			$vipif = $group[0]['int'];
566
		}
567

    
568
		$interfaces[$name] = sprintf(gettext("GW Group %s"), $name);
569
	}
570

    
571
	return($interfaces);
572

    
573
}
574

    
575
function build_auth_method_list() {
576
	global $p1_authentication_methods, $pconfig;
577

    
578
	$list = array();
579

    
580
	foreach ($p1_authentication_methods as $method_type => $method_params) {
581
		if (!$pconfig['mobile'] && $method_params['mobile']) {
582
			continue;
583
		}
584

    
585
		$list[$method_type] = htmlspecialchars($method_params['name']);
586
	}
587

    
588
	return($list);
589
}
590

    
591
function build_myid_list() {
592
	global $my_identifier_list;
593

    
594
	$list = array();
595

    
596
	foreach ($my_identifier_list as $id_type => $id_params) {
597
		$list[$id_type] = htmlspecialchars($id_params['desc']);
598
	}
599

    
600
	return($list);
601
}
602

    
603
function build_peerid_list() {
604
	global $peer_identifier_list;
605

    
606
	$list = array();
607

    
608
	foreach ($peer_identifier_list as $id_type => $id_params) {
609
		$list[$id_type] = htmlspecialchars($id_params['desc']);
610
	}
611

    
612
	return($list);
613
}
614

    
615
function build_cert_list() {
616
	global $config;
617

    
618
	$list = array();
619

    
620
	if (is_array($config['cert'])) {
621
		foreach ($config['cert'] as $cert) {
622
			$list[$cert['refid']] = $cert['descr'];
623
		}
624
	}
625

    
626
	return($list);
627
}
628

    
629
function build_ca_list() {
630
	global $config;
631

    
632
	$list = array();
633

    
634
	if (is_array($config['ca'])) {
635
		foreach ($config['ca'] as $ca) {
636
			$list[$ca['refid']] = $ca['descr'];
637
		}
638
	}
639

    
640
	return($list);
641
}
642

    
643
function build_eal_list() {
644
	global $p1_ealgos;
645

    
646
	$list = array();
647

    
648
	if (is_array($p1_ealgos)) {
649
		foreach ($p1_ealgos as $algo => $algodata) {
650
			$list[$algo] = htmlspecialchars($algodata['name']);
651
		}
652
	}
653

    
654
	return($list);
655
}
656

    
657
if ($pconfig['mobile']) {
658
	$pgtitle = array(gettext("VPN"), gettext("IPsec"), gettext("Mobile Clients"), gettext("Edit Phase 1"));
659
	$pglinks = array("", "vpn_ipsec.php", "vpn_ipsec_mobile.php", "@self");
660
} else {
661
	$pgtitle = array(gettext("VPN"), gettext("IPsec"), gettext("Tunnels"), gettext("Edit Phase 1"));
662
	$pglinks = array("", "vpn_ipsec.php", "vpn_ipsec.php", "@self");
663
}
664

    
665
$shortcut_section = "ipsec";
666

    
667
include("head.inc");
668

    
669
if ($input_errors) {
670
	print_input_errors($input_errors);
671
}
672

    
673
$tab_array = array();
674
$tab_array[] = array(gettext("Tunnels"), true, "vpn_ipsec.php");
675
$tab_array[] = array(gettext("Mobile Clients"), false, "vpn_ipsec_mobile.php");
676
$tab_array[] = array(gettext("Pre-Shared Keys"), false, "vpn_ipsec_keys.php");
677
$tab_array[] = array(gettext("Advanced Settings"), false, "vpn_ipsec_settings.php");
678
display_top_tabs($tab_array);
679

    
680
$form = new Form();
681

    
682
$section = new Form_Section('General Information');
683

    
684
$section->addInput(new Form_Checkbox(
685
	'disabled',
686
	'Disabled',
687
	'Set this option to disable this phase1 without removing it from the list. ',
688
	$pconfig['disabled']
689
));
690

    
691
$section->addInput(new Form_Select(
692
	'iketype',
693
	'*Key Exchange version',
694
	$pconfig['iketype'],
695
	array("ikev1" => "IKEv1", "ikev2" => "IKEv2", "auto" => gettext("Auto"))
696
))->setHelp('Select the Internet Key Exchange protocol version to be used. Auto uses IKEv2 when initiator, and accepts either IKEv1 or IKEv2 as responder.');
697

    
698
$section->addInput(new Form_Select(
699
	'protocol',
700
	'*Internet Protocol',
701
	$pconfig['protocol'],
702
	array("inet" => "IPv4", "inet6" => "IPv6", "both" => "Both (Dual Stack)")
703
))->setHelp('Select the Internet Protocol family.');
704

    
705
$section->addInput(new Form_Select(
706
	'interface',
707
	'*Interface',
708
	$pconfig['interface'],
709
	build_interface_list()
710
))->setHelp('Select the interface for the local endpoint of this phase1 entry.');
711

    
712
if (!$pconfig['mobile']) {
713
	$section->addInput(new Form_Input(
714
		'remotegw',
715
		'*Remote Gateway',
716
		'text',
717
		$pconfig['remotegw']
718
	))->setHelp('Enter the public IP address or host name of the remote gateway.');
719
}
720

    
721
$section->addInput(new Form_Input(
722
	'descr',
723
	'Description',
724
	'text',
725
	$pconfig['descr']
726
))->setHelp('A description may be entered here for administrative reference (not parsed).');
727

    
728
$form->add($section);
729

    
730
$section = new Form_Section('Phase 1 Proposal (Authentication)');
731

    
732
$section->addInput(new Form_Select(
733
	'authentication_method',
734
	'*Authentication Method',
735
	$pconfig['authentication_method'],
736
	build_auth_method_list()
737
))->setHelp('Must match the setting chosen on the remote side.');
738

    
739
$section->addInput(new Form_Select(
740
	'mode',
741
	'*Negotiation mode',
742
	$pconfig['mode'],
743
	array("main" => gettext("Main"), "aggressive" => gettext("Aggressive"))
744
))->setHelp('Aggressive is more flexible, but less secure.');
745

    
746
$group = new Form_Group('*My identifier');
747

    
748
$group->add(new Form_Select(
749
	'myid_type',
750
	null,
751
	$pconfig['myid_type'],
752
	build_myid_list()
753
));
754

    
755
$group->add(new Form_Input(
756
	'myid_data',
757
	null,
758
	'text',
759
	$pconfig['myid_data']
760
));
761

    
762
$section->add($group);
763

    
764
$group = new Form_Group('*Peer identifier');
765
$group->addClass('peeridgroup');
766

    
767
$group->add(new Form_Select(
768
	'peerid_type',
769
	null,
770
	$pconfig['peerid_type'],
771
	build_peerid_list()
772
));
773

    
774
$group->add(new Form_Input(
775
	'peerid_data',
776
	null,
777
	'text',
778
	$pconfig['peerid_data']
779
));
780

    
781
if ($pconfig['mobile']) {
782
	$group->setHelp('This is known as the "group" setting on some VPN client implementations');
783
}
784

    
785
$section->add($group);
786

    
787
$section->addInput(new Form_Input(
788
	'pskey',
789
	'*Pre-Shared Key',
790
	'text',
791
	$pconfig['pskey']
792
))->setHelp('Enter the Pre-Shared Key string.');
793

    
794
$section->addInput(new Form_Select(
795
	'certref',
796
	'*My Certificate',
797
	$pconfig['certref'],
798
	build_cert_list()
799
))->setHelp('Select a certificate previously configured in the Certificate Manager.');
800

    
801
$section->addInput(new Form_Select(
802
	'caref',
803
	'*Peer Certificate Authority',
804
	$pconfig['caref'],
805
	build_ca_list()
806
))->setHelp('Select a certificate authority previously configured in the Certificate Manager.');
807

    
808
$form->add($section);
809

    
810
$rowcount = count($pconfig['encryption']['item']);
811
$section = new Form_Section('Phase 1 Proposal (Encryption Algorithm)');
812
foreach($pconfig['encryption']['item'] as $key => $p1enc) {
813
	$lastrow = ($counter == $rowcount - 1);
814
	$group = new Form_Group($counter == 0 ? '*Encryption Algorithm' : '');
815
	$group->addClass("repeatable");
816

    
817
	$group->add(new Form_Select(
818
		'ealgo_algo'.$key,
819
		null,
820
		$p1enc['encryption-algorithm']['name'],
821
		build_eal_list()
822
	))->setHelp($lastrow ? 'Algorithm' : '');
823

    
824
	$group->add(new Form_Select(
825
		'ealgo_keylen'.$key,
826
		null,
827
		$p1enc['encryption-algorithm']['keylen'],
828
		array()
829
	))->setHelp($lastrow ? 'Key length' : '');
830

    
831
	$group->add(new Form_Select(
832
		'halgo'.$key,
833
		'*Hash Algorithm',
834
		$p1enc['hash-algorithm'],
835
		$p1_halgos
836
	))->setHelp($lastrow ? 'Hash' : '');
837

    
838
	$group->add(new Form_Select(
839
		'dhgroup'.$key,
840
		'*DH Group',
841
		$p1enc['dhgroup'],
842
		$p1_dhgroups
843
	))->setHelp($lastrow ? 'DH Group' : '');
844

    
845
	$group->add(new Form_Button(
846
		'deleterow' . $counter,
847
		'Delete',
848
		null,
849
		'fa-trash'
850
	))->addClass('btn-warning');
851

    
852
	$section->add($group);
853
	$counter += 1;
854
}
855
$form->add($section);
856

    
857
$btnaddopt = new Form_Button(
858
	'algoaddrow',
859
	'Add Algorithm',
860
	null,
861
	'fa-plus'
862
);
863
$btnaddopt->removeClass('btn-primary')->addClass('btn-success btn-sm');
864
$section->addInput($btnaddopt);
865

    
866
$section = new Form_Section('NOTITLE');
867
$section->addInput(new Form_Input(
868
	'lifetime',
869
	'*Lifetime (Seconds)',
870
	'number',
871
	$pconfig['lifetime']
872
));
873

    
874
$form->add($section);
875

    
876
$section = new Form_Section('Advanced Options');
877

    
878
$section->addInput(new Form_Checkbox(
879
	'rekey_enable',
880
	'Disable rekey',
881
	'Disables renegotiation when a connection is about to expire.',
882
	$pconfig['rekey_enable']
883
));
884

    
885
$section->addInput(new Form_Input(
886
	'margintime',
887
	'Margintime (Seconds)',
888
	'number',
889
	$pconfig['margintime']
890
))->setHelp('How long before connection expiry or keying-channel expiry should attempt to negotiate a replacement begin.');
891

    
892
$section->addInput(new Form_Checkbox(
893
	'reauth_enable',
894
	'Disable Reauth',
895
	'Whether rekeying of an IKE_SA should also reauthenticate the peer. In IKEv1, reauthentication is always done.',
896
	$pconfig['reauth_enable']
897
));
898

    
899
$section->addInput(new Form_Checkbox(
900
	'responderonly',
901
	'Responder Only',
902
	'Enable this option to never initiate this connection from this side, only respond to incoming requests.',
903
	$pconfig['responderonly']
904
));
905

    
906
$section->addInput(new Form_Select(
907
	'nat_traversal',
908
	'NAT Traversal',
909
	$pconfig['nat_traversal'],
910
	array('on' => gettext('Auto'), 'force' => gettext('Force'))
911
))->setHelp('Set this option to enable the use of NAT-T (i.e. the encapsulation of ESP in UDP packets) if needed, ' .
912
			'which can help with clients that are behind restrictive firewalls.');
913

    
914
$section->addInput(new Form_Select(
915
	'mobike',
916
	'MOBIKE',
917
	$pconfig['mobike'],
918
	array('on' => gettext('Enable'), 'off' => gettext('Disable'))
919
))->setHelp('Set this option to control the use of MOBIKE');
920

    
921
$section->addInput(new Form_Checkbox(
922
	'splitconn',
923
	'Split connections',
924
	'Enable this to split connection entries with multiple phase 2 configurations. Required for remote endpoints that support only a single traffic selector per child SA.',
925
	$pconfig['splitconn']
926
));
927

    
928
/* FreeBSD doesn't yet have TFC support. this is ready to go once it does
929
https://redmine.pfsense.org/issues/4688
930

    
931
$section->addInput(new Form_Checkbox(
932
	'tfc_enable',
933
	'Traffic Flow Confidentiality',
934
	'Enable TFC',
935
	$pconfig['tfc_enable']
936
))->setHelp('Enable Traffic Flow Confidentiality');
937

    
938
$section->addInput(new Form_Input(
939
	'tfc_bytes',
940
	'TFC Bytes',
941
	'Bytes TFC',
942
	$pconfig['tfc_bytes']
943
))->setHelp('Enter the number of bytes to pad ESP data to, or leave blank to fill to MTU size');
944

    
945
*/
946

    
947
$section->addInput(new Form_Checkbox(
948
	'dpd_enable',
949
	'Dead Peer Detection',
950
	'Enable DPD',
951
	$pconfig['dpd_enable']
952
));
953

    
954
$section->addInput(new Form_Input(
955
	'dpd_delay',
956
	'Delay',
957
	'number',
958
	$pconfig['dpd_delay']
959
))->setHelp('Delay between requesting peer acknowledgement.');
960

    
961
$section->addInput(new Form_Input(
962
	'dpd_maxfail',
963
	'Max failures',
964
	'number',
965
	$pconfig['dpd_maxfail']
966
))->setHelp('Number of consecutive failures allowed before disconnect. ');
967

    
968
if (isset($p1index) && $a_phase1[$p1index]) {
969
	$section->addInput(new Form_Input(
970
		'p1index',
971
		null,
972
		'hidden',
973
		$p1index
974
	));
975
}
976

    
977
if ($pconfig['mobile']) {
978
	$section->addInput(new Form_Input(
979
		'mobile',
980
		null,
981
		'hidden',
982
		'true'
983
	));
984
}
985

    
986
$section->addInput(new Form_Input(
987
	'ikeid',
988
	null,
989
	'hidden',
990
	$pconfig['ikeid']
991
));
992

    
993
$form->add($section);
994

    
995
print($form);
996

    
997
?>
998

    
999

    
1000
<form action="vpn_ipsec_phase1.php" method="post" name="iform" id="iform">
1001

    
1002
<script type="text/javascript">
1003
//<![CDATA[
1004
events.push(function() {
1005

    
1006
	$('[id^=algoaddrow]').prop('type','button');
1007

    
1008
	$('[id^=algoaddrow]').click(function() {
1009
		add_row();
1010

    
1011
		var lastRepeatableGroup = $('.repeatable:last');
1012
		$(lastRepeatableGroup).find('[id^=ealgo_algo]select').change(function () {
1013
			id = getStringInt(this.id);
1014
			ealgosel_change(id, '');
1015
		});
1016
		$(lastRepeatableGroup).find('[id^=ealgo_algo]select').change();
1017
	});
1018

    
1019
	function myidsel_change() {
1020
		hideGroupInput('myid_data', ($('#myid_type').val() == 'myaddress'));
1021
	}
1022

    
1023
	function iketype_change() {
1024

    
1025
		if ($('#iketype').val() == 'ikev2') {
1026
			hideInput('mode', true);
1027
			hideInput('mobike', false);
1028
			hideInput('nat_traversal', true);
1029
			//hideCheckbox('tfc_enable', false);
1030
			hideCheckbox('reauth_enable', false);
1031
			hideCheckbox('splitconn', false);
1032
		} else {
1033
			hideInput('mode', false);
1034
			hideInput('mobike', true);
1035
			hideInput('nat_traversal', false);
1036
			//hideCheckbox('tfc_enable', true);
1037
			//hideInput('tfc_bytes', true);
1038
			hideCheckbox('reauth_enable', true);
1039
			hideCheckbox('splitconn', true);
1040
		}
1041
	}
1042

    
1043
	function peeridsel_change() {
1044
		hideGroupInput('peerid_data', ($('#peerid_type').val() == 'peeraddress') || ($('#peerid_type').val() == 'any'));
1045
	}
1046

    
1047
	function methodsel_change() {
1048

    
1049
		switch ($('#authentication_method').val()) {
1050
			case 'eap-mschapv2':
1051
			case 'eap-radius':
1052
			case 'hybrid_rsa_server':
1053
				hideInput('pskey', true);
1054
				hideClass('peeridgroup', false);
1055
				hideInput('certref', false);
1056
				hideInput('caref', true);
1057
				disableInput('certref', false);
1058
				disableInput('caref', true);
1059
				break;
1060
			case 'eap-tls':
1061
			case 'xauth_rsa_server':
1062
			case 'rsasig':
1063
				hideInput('pskey', true);
1064
				hideClass('peeridgroup', false);
1065
				hideInput('certref', false);
1066
				hideInput('caref', false);
1067
				disableInput('certref', false);
1068
				disableInput('caref', false);
1069
				break;
1070

    
1071
<?php if ($pconfig['mobile']) { ?>
1072
				case 'pre_shared_key':
1073
					hideInput('pskey', true);
1074
					hideClass('peeridgroup', true);
1075
					hideInput('certref', true);
1076
					hideInput('caref', true);
1077
					disableInput('certref', true);
1078
					disableInput('caref', true);
1079
					break;
1080
<?php } ?>
1081
			default: /* psk modes*/
1082
				hideInput('pskey', false);
1083
				hideClass('peeridgroup', false);
1084
				hideInput('certref', true);
1085
				hideInput('caref', true);
1086
				disableInput('certref', true);
1087
				disableInput('caref', true);
1088
				break;
1089
		}
1090
	}
1091

    
1092
	/* PHP generates javascript case statements for variable length keys */
1093
	function ealgosel_change(id, bits) {
1094

    
1095
		$("select[name='ealgo_keylen"+id+"']").find('option').remove().end();
1096

    
1097
		switch ($('#ealgo_algo'+id).find(":selected").index().toString()) {
1098
<?php
1099
	$i = 0;
1100
	foreach ($p1_ealgos as $algo => $algodata) {
1101
		if (is_array($algodata['keysel'])) {
1102
?>
1103
			case '<?=$i?>':
1104
				invisibleGroupInput('ealgo_keylen'+id, false);
1105
<?php
1106
			$key_hi = $algodata['keysel']['hi'];
1107
			$key_lo = $algodata['keysel']['lo'];
1108
			$key_step = $algodata['keysel']['step'];
1109

    
1110
			for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
1111
?>
1112
				$("select[name='ealgo_keylen"+id+"']").append($('<option value="<?=$keylen?>"><?=$keylen?> bits</option>'));
1113
<?php
1114
			}
1115
?>
1116
			break;
1117
<?php
1118
		} else {
1119
?>
1120
			case '<?=$i?>':
1121
				invisibleGroupInput('ealgo_keylen'+id, true);
1122
			break;
1123
<?php
1124
		}
1125
		$i++;
1126
	}
1127
?>
1128
		}
1129

    
1130
		if (bits) {
1131
			$('#ealgo_keylen'+id).val(bits);
1132
		}
1133
	}
1134

    
1135
	function rekeychkbox_change() {
1136
		hide = $('#rekey_enable').prop('checked');
1137

    
1138
		hideInput('margintime', hide);
1139
  }
1140

    
1141
	function dpdchkbox_change() {
1142
		hide = !$('#dpd_enable').prop('checked');
1143

    
1144
		hideInput('dpd_delay', hide);
1145
		hideInput('dpd_maxfail', hide);
1146

    
1147
		if (!$('#dpd_delay').val()) {
1148
			$('#dpd_delay').val('10')
1149
		}
1150

    
1151
		if (!$('#dpd_maxfail').val()) {
1152
			$('#dpd_maxfail').val('5')
1153
		}
1154
	}
1155

    
1156
	//function tfcchkbox_change() {
1157
	//	hide = !$('#tfc_enable').prop('checked');
1158
	//
1159
	//	hideInput('tfc_bytes', hide);
1160
	//}
1161

    
1162
	// ---------- Monitor elements for change and call the appropriate display functions ----------
1163

    
1164
	 // Enable Rekey
1165
	$('#rekey_enable').click(function () {
1166
		rekeychkbox_change();
1167
	});
1168

    
1169
	 // Enable DPD
1170
	$('#dpd_enable').click(function () {
1171
		dpdchkbox_change();
1172
	});
1173

    
1174
	 // TFC
1175
	//$('#tfc_enable').click(function () {
1176
	//	tfcchkbox_change();
1177
	//});
1178

    
1179
	 // Peer identifier
1180
	$('#peerid_type').change(function () {
1181
		peeridsel_change();
1182
	});
1183

    
1184
	 // My identifier
1185
	$('#myid_type').change(function () {
1186
		myidsel_change();
1187
	});
1188

    
1189
	 // ike type
1190
	$('#iketype').change(function () {
1191
		iketype_change();
1192
	});
1193

    
1194
	 // authentication method
1195
	$('#authentication_method').change(function () {
1196
		methodsel_change();
1197
	});
1198

    
1199
	 // algorithm
1200
	$('[id^=ealgo_algo]select').change(function () {
1201
		id = getStringInt(this.id);
1202
//		ealgosel_change(id, <?=$keyset?>);
1203
		ealgosel_change(id, 0);
1204
	});
1205

    
1206
	// On ititial page load
1207
	myidsel_change();
1208
	peeridsel_change();
1209
	iketype_change();
1210
	methodsel_change();
1211
	rekeychkbox_change();
1212
	dpdchkbox_change();
1213
<?php
1214
foreach($pconfig['encryption']['item'] as $key => $p1enc) {
1215
	$keylen = $p1enc['encryption-algorithm']['keylen'];
1216
	if (!is_numericint($keylen)) {
1217
		$keylen = "''";
1218
	}
1219
	echo "ealgosel_change({$key}, {$keylen});";
1220
}
1221
?>
1222

    
1223
	// ---------- On initial page load ------------------------------------------------------------
1224

    
1225
	hideInput('ikeid', true);
1226
});
1227
//]]>
1228
</script>
1229
</form>
1230
<?php
1231

    
1232
include("foot.inc");
    (1-1/1)