1
|
<?php
|
2
|
/*
|
3
|
* vpn_ipsec.php
|
4
|
*
|
5
|
* part of pfSense (https://www.pfsense.org)
|
6
|
* Copyright (c) 2004-2013 BSD Perimeter
|
7
|
* Copyright (c) 2013-2016 Electric Sheep Fencing
|
8
|
* Copyright (c) 2014-2024 Rubicon Communications, LLC (Netgate)
|
9
|
* All rights reserved.
|
10
|
*
|
11
|
* originally based on m0n0wall (http://m0n0.ch/wall)
|
12
|
* Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
|
13
|
* All rights reserved.
|
14
|
*
|
15
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
16
|
* you may not use this file except in compliance with the License.
|
17
|
* You may obtain a copy of the License at
|
18
|
*
|
19
|
* http://www.apache.org/licenses/LICENSE-2.0
|
20
|
*
|
21
|
* Unless required by applicable law or agreed to in writing, software
|
22
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
23
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
24
|
* See the License for the specific language governing permissions and
|
25
|
* limitations under the License.
|
26
|
*/
|
27
|
|
28
|
##|+PRIV
|
29
|
##|*IDENT=page-vpn-ipsec
|
30
|
##|*NAME=VPN: IPsec
|
31
|
##|*DESCR=Allow access to the 'VPN: IPsec' page.
|
32
|
##|*MATCH=vpn_ipsec.php*
|
33
|
##|-PRIV
|
34
|
|
35
|
require_once("guiconfig.inc");
|
36
|
require_once("functions.inc");
|
37
|
require_once("filter.inc");
|
38
|
require_once("shaper.inc");
|
39
|
require_once("ipsec.inc");
|
40
|
require_once("vpn.inc");
|
41
|
|
42
|
global $p1_authentication_methods;
|
43
|
|
44
|
init_config_arr(array('ipsec', 'phase1'));
|
45
|
init_config_arr(array('ipsec', 'phase2'));
|
46
|
|
47
|
$items_deleted = false;
|
48
|
|
49
|
if ($_POST['apply']) {
|
50
|
$ipsec_dynamic_hosts = ipsec_configure();
|
51
|
ipsec_reload_package_hook();
|
52
|
/* reload the filter in the background */
|
53
|
$retval = 0;
|
54
|
$retval |= filter_configure();
|
55
|
if ($ipsec_dynamic_hosts >= 0) {
|
56
|
if (is_subsystem_dirty('ipsec')) {
|
57
|
clear_subsystem_dirty('ipsec');
|
58
|
}
|
59
|
}
|
60
|
} else if (isset($_POST['del'])) {
|
61
|
/* delete selected p1 entries */
|
62
|
if (is_array($_POST['p1entry']) && count($_POST['p1entry'])) {
|
63
|
$delcount = delete_p1_and_children($_POST['p1entry']);
|
64
|
|
65
|
if ($delcount > 0) {
|
66
|
if (write_config(gettext("Deleted selected IPsec Phase 1 and related Phase 2 entries."))) {
|
67
|
mark_subsystem_dirty('ipsec');
|
68
|
}
|
69
|
}
|
70
|
}
|
71
|
} else if (isset($_POST['delp2'])) {
|
72
|
/* delete selected p2 entries */
|
73
|
if (is_array($_POST['p2entry']) && count($_POST['p2entry'])) {
|
74
|
foreach ($_POST['p2entry'] as $p2entrydel) {
|
75
|
if (is_interface_ipsec_vti_assigned(config_get_path('ipsec/phase2/' . $p2entrydel)) && (config_get_path('ipsec/phase2/' . $p2entrydel . '/mode') == 'vti')) {
|
76
|
$input_errors[] = gettext("Cannot delete a VTI Phase 2 while the interface is assigned. Remove the interface assignment before deleting this P2.");
|
77
|
} else {
|
78
|
config_del_path('ipsec/phase2/' . $p2entrydel);
|
79
|
$items_deleted = true;
|
80
|
}
|
81
|
}
|
82
|
if ($items_deleted) {
|
83
|
if (write_config(gettext("Deleted selected IPsec Phase 2 entries."))) {
|
84
|
mark_subsystem_dirty('ipsec');
|
85
|
}
|
86
|
}
|
87
|
}
|
88
|
} else {
|
89
|
/* yuck - IE won't send value attributes for image buttons, while Mozilla does - so we use .x/.y to find move button clicks instead... */
|
90
|
|
91
|
// TODO: this. is. nasty.
|
92
|
unset($delbtn, $delbtnp2, $movebtn, $movebtnp2, $togglebtn, $togglebtnp2);
|
93
|
foreach ($_POST as $pn => $pd) {
|
94
|
if (preg_match("/del_(\d+)/", $pn, $matches)) {
|
95
|
$delbtn = $matches[1];
|
96
|
} else if (preg_match("/delp2_(\d+)/", $pn, $matches)) {
|
97
|
$delbtnp2 = $matches[1];
|
98
|
} else if (preg_match("/move_(\d+)/", $pn, $matches)) {
|
99
|
$movebtn = $matches[1];
|
100
|
} else if (preg_match("/movep2_(\d+)/", $pn, $matches)) {
|
101
|
$movebtnp2 = $matches[1];
|
102
|
} else if (preg_match("/toggle_(\d+)/", $pn, $matches)) {
|
103
|
$togglebtn = $matches[1];
|
104
|
} else if (preg_match("/togglep2_(\d+)/", $pn, $matches)) {
|
105
|
$togglebtnp2 = $matches[1];
|
106
|
}
|
107
|
}
|
108
|
|
109
|
$save = 1;
|
110
|
|
111
|
/* move selected p1 entries before this */
|
112
|
if (isset($movebtn) && is_array($_POST['p1entry']) && count($_POST['p1entry'])) {
|
113
|
$a_phase1_new = array();
|
114
|
|
115
|
/* copy all p1 entries < $movebtn and not selected */
|
116
|
for ($i = 0; $i < $movebtn; $i++) {
|
117
|
if (!in_array($i, $_POST['p1entry'])) {
|
118
|
$a_phase1_new[] = config_get_path('ipsec/phase1/' . $i);
|
119
|
}
|
120
|
}
|
121
|
|
122
|
/* copy all selected p1 entries */
|
123
|
for ($i = 0; $i < count(config_get_path('ipsec/phase1', [])); $i++) {
|
124
|
if ($i == $movebtn) {
|
125
|
continue;
|
126
|
}
|
127
|
if (in_array($i, $_POST['p1entry'])) {
|
128
|
$a_phase1_new[] = config_get_path('ipsec/phase1/' . $i);
|
129
|
}
|
130
|
}
|
131
|
|
132
|
/* copy $movebtn p1 entry */
|
133
|
if ($movebtn < count(config_get_path('ipsec/phase1', []))) {
|
134
|
$a_phase1_new[] = config_get_path('ipsec/phase1/' . $movebtn);
|
135
|
}
|
136
|
|
137
|
/* copy all p1 entries > $movebtn and not selected */
|
138
|
for ($i = $movebtn+1; $i < count(config_get_path('ipsec/phase1', [])); $i++) {
|
139
|
if (!in_array($i, $_POST['p1entry'])) {
|
140
|
$a_phase1_new[] = config_get_path('ipsec/phase1/' . $i);
|
141
|
}
|
142
|
}
|
143
|
if (count($a_phase1_new) > 0) {
|
144
|
config_set_path('ipsec/phase1', $a_phase1_new);
|
145
|
}
|
146
|
|
147
|
} else if (isset($movebtnp2) && is_array($_POST['p2entry']) && count($_POST['p2entry'])) {
|
148
|
/* move selected p2 entries before this */
|
149
|
$a_phase2_new = array();
|
150
|
|
151
|
/* copy all p2 entries < $movebtnp2 and not selected */
|
152
|
for ($i = 0; $i < $movebtnp2; $i++) {
|
153
|
if (!in_array($i, $_POST['p2entry'])) {
|
154
|
$a_phase2_new[] = config_get_path('ipsec/phase2/' . $i);
|
155
|
}
|
156
|
}
|
157
|
|
158
|
/* copy all selected p2 entries */
|
159
|
for ($i = 0; $i < count(config_get_path('ipsec/phase2', [])); $i++) {
|
160
|
if ($i == $movebtnp2) {
|
161
|
continue;
|
162
|
}
|
163
|
if (in_array($i, $_POST['p2entry'])) {
|
164
|
$a_phase2_new[] = config_get_path('ipsec/phase2/' . $i);
|
165
|
}
|
166
|
}
|
167
|
|
168
|
/* copy $movebtnp2 p2 entry */
|
169
|
if ($movebtnp2 < count(config_get_path('ipsec/phase2', []))) {
|
170
|
$a_phase2_new[] = config_get_path('ipsec/phase2/' . $movebtnp2);
|
171
|
}
|
172
|
|
173
|
/* copy all p2 entries > $movebtnp2 and not selected */
|
174
|
for ($i = $movebtnp2+1; $i < count(config_get_path('ipsec/phase2', [])); $i++) {
|
175
|
if (!in_array($i, $_POST['p2entry'])) {
|
176
|
$a_phase2_new[] = config_get_path('ipsec/phase2/' . $i);
|
177
|
}
|
178
|
}
|
179
|
if (count($a_phase2_new) > 0) {
|
180
|
config_set_path('ipsec/phase2', $a_phase2_new);
|
181
|
}
|
182
|
|
183
|
} else if (isset($togglebtn)) {
|
184
|
if (config_path_enabled('ipsec/phase1/' . $togglebtn, 'disabled')) {
|
185
|
config_del_path('ipsec/phase1/' . $togglebtn . '/disabled');
|
186
|
} else {
|
187
|
if (ipsec_vti(config_get_path('ipsec/phase1/' . $togglebtn), false, false)) {
|
188
|
/* disable all phase2 entries that match the ikeid */
|
189
|
$ikeid = config_get_path('ipsec/phase1/' . $togglebtn . '/ikeid');
|
190
|
$p1_has_vti = false;
|
191
|
$disablep2ids = array();
|
192
|
foreach (config_get_path('ipsec/phase2') as $p2index => $ph2tmp) {
|
193
|
if ($ph2tmp['ikeid'] == $ikeid) {
|
194
|
if (is_interface_ipsec_vti_assigned($ph2tmp)) {
|
195
|
$p1_has_vti = true;
|
196
|
} else {
|
197
|
$disablep2ids[] = $p2index;
|
198
|
}
|
199
|
}
|
200
|
}
|
201
|
|
202
|
if ($p1_has_vti) {
|
203
|
$input_errors[] = gettext("Cannot disable a Phase 1 which contains an active VTI Phase 2 with an interface assigned. Remove the interface assignment before deleting this P1.");
|
204
|
} else {
|
205
|
foreach ($disablep2ids as $dp2idx) {
|
206
|
config_set_path('ipsec/phase2/' . $togglebtnp2 . '/disabled', true);
|
207
|
}
|
208
|
config_set_path('ipsec/phase1/' . $togglebtn . '/disabled', true);
|
209
|
}
|
210
|
} else {
|
211
|
config_set_path('ipsec/phase1/' . $togglebtn . '/disabled', true);
|
212
|
}
|
213
|
}
|
214
|
} else if (isset($togglebtnp2)) {
|
215
|
if (config_path_enabled('ipsec/phase2/' . $togglebtnp2, 'disabled')) {
|
216
|
config_del_path('ipsec/phase2/' . $togglebtnp2 . '/disabled');
|
217
|
} else {
|
218
|
if (is_interface_ipsec_vti_assigned(config_get_path('ipsec/phase2/' . $togglebtnp2)) && (config_get_path('ipsec/phase2/' . $togglebtnp2 . '/mode') == 'vti')) {
|
219
|
$input_errors[] = gettext("Cannot disable a VTI Phase 2 while the interface is assigned. Remove the interface assignment before disabling this P2.");
|
220
|
} else {
|
221
|
config_set_path('ipsec/phase2/' . $togglebtnp2 . '/disabled', true);
|
222
|
}
|
223
|
}
|
224
|
} else if (isset($delbtn)) {
|
225
|
$delcount = delete_p1_and_children([$delbtn]);
|
226
|
|
227
|
if ($delcount > 0) {
|
228
|
/* Use a better description than generic save below */
|
229
|
$save = 0;
|
230
|
if (write_config(gettext("Deleted selected IPsec Phase 1 and related Phase 2 entries."))) {
|
231
|
mark_subsystem_dirty('ipsec');
|
232
|
}
|
233
|
}
|
234
|
} else if (isset($delbtnp2)) {
|
235
|
if (is_interface_ipsec_vti_assigned(config_get_path('ipsec/phase2/' . $delbtnp2)) && (config_get_path('ipsec/phase2/' . $delbtnp2 . '/mode') == 'vti')) {
|
236
|
$input_errors[] = gettext("Cannot delete a VTI Phase 2 while the interface is assigned. Remove the interface assignment before deleting this P2.");
|
237
|
} else {
|
238
|
config_del_path('ipsec/phase2/' . $delbtnp2);
|
239
|
$items_deleted = true;
|
240
|
}
|
241
|
} else {
|
242
|
$save = 0;
|
243
|
}
|
244
|
|
245
|
if ($save === 1) {
|
246
|
if (write_config(gettext("Saved configuration changes for IPsec tunnels."))) {
|
247
|
mark_subsystem_dirty('ipsec');
|
248
|
}
|
249
|
}
|
250
|
}
|
251
|
|
252
|
$pgtitle = array(gettext("VPN"), gettext("IPsec"), gettext("Tunnels"));
|
253
|
$pglinks = array("", "@self", "@self");
|
254
|
$shortcut_section = "ipsec";
|
255
|
|
256
|
include("head.inc");
|
257
|
|
258
|
if ($input_errors) {
|
259
|
print_input_errors($input_errors);
|
260
|
}
|
261
|
|
262
|
$tab_array = array();
|
263
|
$tab_array[] = array(gettext("Tunnels"), true, "vpn_ipsec.php");
|
264
|
$tab_array[] = array(gettext("Mobile Clients"), false, "vpn_ipsec_mobile.php");
|
265
|
$tab_array[] = array(gettext("Pre-Shared Keys"), false, "vpn_ipsec_keys.php");
|
266
|
$tab_array[] = array(gettext("Advanced Settings"), false, "vpn_ipsec_settings.php");
|
267
|
display_top_tabs($tab_array);
|
268
|
|
269
|
if ($_POST['apply']) {
|
270
|
print_apply_result_box($retval);
|
271
|
}
|
272
|
|
273
|
if (is_subsystem_dirty('ipsec')) {
|
274
|
print_apply_box(gettext("The IPsec tunnel configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
|
275
|
}
|
276
|
global $user_settings;
|
277
|
$show_alias_popup = (array_key_exists('webgui', $user_settings) && !$user_settings['webgui']['disablealiaspopupdetail']);
|
278
|
$ipsec_specialnet = get_specialnet('', [SPECIALNET_IFSUB]);
|
279
|
?>
|
280
|
|
281
|
<form name="mainform" method="post">
|
282
|
<div class="panel panel-default">
|
283
|
<div class="panel-heading"><h2 class="panel-title"><?=gettext('IPsec Tunnels')?></h2></div>
|
284
|
<div class="panel-body table-responsive">
|
285
|
<table class="table table-striped table-hover">
|
286
|
<thead>
|
287
|
<tr>
|
288
|
<th> </th>
|
289
|
<th> </th>
|
290
|
<th><?=gettext("ID")?></th>
|
291
|
<th><?=gettext("IKE")?></th>
|
292
|
<th><?=gettext("Remote Gateway")?></th>
|
293
|
<th><?=gettext("Auth")?>/<?=gettext("Mode")?></th>
|
294
|
<th><?=gettext("P1 Protocol")?></th>
|
295
|
<th><?=gettext("P1 Transforms")?></th>
|
296
|
<th><?=gettext("P1 DH-Group")?></th>
|
297
|
<th><?=gettext("P1 Description")?></th>
|
298
|
<th><?=gettext("Actions")?></th>
|
299
|
</tr>
|
300
|
</thead>
|
301
|
<tbody class="p1-entries">
|
302
|
<?php
|
303
|
$iflabels = get_configured_interface_with_descr(true);
|
304
|
$viplist = get_configured_vip_list();
|
305
|
foreach ($viplist as $vip => $address) {
|
306
|
$iflabels[$vip] = $address;
|
307
|
if (get_vip_descr($address)) {
|
308
|
$iflabels[$vip] .= " (". get_vip_descr($address) .")";
|
309
|
}
|
310
|
}
|
311
|
$grouplist = return_gateway_groups_array();
|
312
|
foreach ($grouplist as $name => $group) {
|
313
|
if ($group[0]['vip'] != "") {
|
314
|
$vipif = $group[0]['vip'];
|
315
|
} else {
|
316
|
$vipif = $group[0]['int'];
|
317
|
}
|
318
|
$iflabels[$name] = "GW Group {$name}";
|
319
|
}
|
320
|
|
321
|
$i = 0; foreach (config_get_path('ipsec/phase1', []) as $ph1ent):
|
322
|
|
323
|
$iconfn = "pass";
|
324
|
|
325
|
$entryStatus = (isset($ph1ent['disabled']) ? 'disabled' : 'enabled');
|
326
|
|
327
|
if ($entryStatus == 'disabled') {
|
328
|
$iconfn .= "_d";
|
329
|
}
|
330
|
?>
|
331
|
<tr id="fr<?=$i?>" onclick="fr_toggle(<?=$i?>)" id="frd<?=$i?>" ondblclick="document.location='vpn_ipsec_phase1.php?p1index=<?=$i?>'" class="<?= $entryStatus ?>">
|
332
|
<td>
|
333
|
<input type="checkbox" id="frc<?=$i?>" onclick="fr_toggle(<?=$i?>)" name="p1entry[]" value="<?=$i?>" />
|
334
|
<a class="fa-solid fa-anchor icon-pointer" id="Xmove_<?=$i?>" title="<?=gettext("Move checked entries to here")?>"></a>
|
335
|
</td>
|
336
|
<td>
|
337
|
<button value="toggle_<?=$i?>" name="toggle_<?=$i?>" title="<?=gettext("click to toggle enabled/disabled status")?>" class="btn btn-xs btn-<?= ($entryStatus == 'disabled' ? 'success' : 'warning') ?>" type="submit"><?= ($entryStatus == 'disabled' ? 'Enable' : 'Disable') ?></button>
|
338
|
</td>
|
339
|
<td>
|
340
|
<?= htmlspecialchars($ph1ent['ikeid']) ?>
|
341
|
</td>
|
342
|
<td id="frd<?=$i?>">
|
343
|
<?php
|
344
|
if (empty($ph1ent['iketype']) || $ph1ent['iketype'] == "ikev1") {
|
345
|
echo "V1";
|
346
|
} elseif ($ph1ent['iketype'] == "ikev2") {
|
347
|
echo "V2";
|
348
|
} elseif ($ph1ent['iketype'] == "auto") {
|
349
|
echo "Auto";
|
350
|
}
|
351
|
?>
|
352
|
</td>
|
353
|
<td>
|
354
|
<?php
|
355
|
if ($ph1ent['interface']) {
|
356
|
if (isset($iflabels[$ph1ent['interface']])) {
|
357
|
$if = htmlspecialchars($iflabels[$ph1ent['interface']]);
|
358
|
} else {
|
359
|
$if = sprintf("Interface not found: '%s'", $ph1ent['interface']);
|
360
|
}
|
361
|
} else {
|
362
|
$if = "WAN";
|
363
|
}
|
364
|
|
365
|
if (!isset($ph1ent['mobile'])) {
|
366
|
echo $if."<br />".$ph1ent['remote-gateway'];
|
367
|
} else {
|
368
|
echo $if."<br /><strong>" . gettext("Mobile Clients") . "</strong>";
|
369
|
}
|
370
|
?>
|
371
|
</td>
|
372
|
<td id="frd<?=$i?>">
|
373
|
<?php
|
374
|
$authtype = array_get_path($p1_authentication_methods, "{$ph1ent['authentication_method']}/name", '');
|
375
|
if (!empty($authtype)) {
|
376
|
echo "{$authtype}<br/>";
|
377
|
}
|
378
|
if (empty($ph1ent['iketype']) || $ph1ent['iketype'] == "ikev1" || $ph1ent['iketype'] == "auto") {
|
379
|
echo "{$ph1ent['mode']}";
|
380
|
} else {
|
381
|
echo "-";
|
382
|
}
|
383
|
?>
|
384
|
</td>
|
385
|
<td id="frd<?=$i?>">
|
386
|
<?php
|
387
|
$first = true;
|
388
|
foreach(array_get_path($ph1ent, 'encryption/item', []) as $p1algo) {
|
389
|
if (!$first) {
|
390
|
echo "<br/>";
|
391
|
}
|
392
|
|
393
|
echo array_get_path($p1_ealgos, array_get_path($p1algo, 'encryption-algorithm/name', '') . '/name', '');
|
394
|
if (array_get_path($p1algo, 'encryption-algorithm/keylen')) {
|
395
|
echo " (" . array_get_path($p1algo, 'encryption-algorithm/keylen') . " " . gettext("bits") . ")";
|
396
|
}
|
397
|
$first = false;
|
398
|
}
|
399
|
?>
|
400
|
</td>
|
401
|
<td>
|
402
|
<?php $first = true;
|
403
|
foreach(array_get_path($ph1ent, 'encryption/item', []) as $p1algo) {
|
404
|
if (!$first) {
|
405
|
echo "<br/>";
|
406
|
}
|
407
|
echo $p1_halgos[$p1algo['hash-algorithm']];
|
408
|
if (isset($ph1ent['prfselect_enable'])) {
|
409
|
echo " / PRF" . $p1_halgos[$p1algo['prf-algorithm']];
|
410
|
}
|
411
|
$first = false;
|
412
|
}
|
413
|
?>
|
414
|
</td>
|
415
|
<td>
|
416
|
<?php $first = true;
|
417
|
foreach(array_get_path($ph1ent, 'encryption/item', []) as $p1algo) {
|
418
|
if (!$first) {
|
419
|
echo "<br/>";
|
420
|
}
|
421
|
echo str_replace(" "," ",$p1_dhgroups[$p1algo['dhgroup']]);
|
422
|
$first = false;
|
423
|
}
|
424
|
?>
|
425
|
</td>
|
426
|
<td>
|
427
|
<?=htmlspecialchars($ph1ent['descr'])?>
|
428
|
</td>
|
429
|
<td style="cursor: pointer;">
|
430
|
<!-- <a class="fa-solid fa-anchor" id="Xmove_<?=$i?>" title="<?=gettext("Move checked entries to here")?>"></a> -->
|
431
|
<button style="display: none;" class="btn btn-default btn-xs" type="submit" id="move_<?=$i?>" name="move_<?=$i?>" value="move_<?=$i?>"><?=gettext("Move checked entries to here")?></button>
|
432
|
<a class="fa-solid fa-pencil" href="vpn_ipsec_phase1.php?ikeid=<?=$ph1ent['ikeid']?>" title="<?=gettext("Edit phase 1 entry"); ?>"></a>
|
433
|
<?php if (!isset($ph1ent['mobile'])): ?>
|
434
|
<a class="fa-regular fa-clone" href="vpn_ipsec_phase1.php?dup=<?=$i?>" title="<?=gettext("Copy phase 1 entry"); ?>"></a>
|
435
|
<?php endif; ?>
|
436
|
<a class="fa-solid fa-trash-can no-confirm" id="Xdel_<?=$i?>" title="<?=gettext('Delete phase 1 entry'); ?>"></a>
|
437
|
<button style="display: none;" class="btn btn-xs btn-warning" type="submit" id="del_<?=$i?>" name="del_<?=$i?>" value="del_<?=$i?>" title="<?=gettext('Delete phase1 entry'); ?>">delete</button>
|
438
|
|
439
|
</td>
|
440
|
</tr>
|
441
|
<tr class="<?= $entryStatus ?>">
|
442
|
<td colspan="1"></td>
|
443
|
<td colspan="10" class="contains-table">
|
444
|
<?php
|
445
|
if (isset($_REQUEST["tdph2-{$i}-visible"])) {
|
446
|
$tdph2_visible = htmlspecialchars($_REQUEST["tdph2-{$i}-visible"]);
|
447
|
} else {
|
448
|
$tdph2_visible = 0;
|
449
|
}
|
450
|
?>
|
451
|
<input type="hidden" name="tdph2-<?=$i?>-visible" id="tdph2-<?=$i?>-visible" value="<?=$tdph2_visible?>" />
|
452
|
<div id="shph2but-<?=$i?>" <?=($tdph2_visible == '1' ? 'style="display:none"' : '')?>>
|
453
|
<?php
|
454
|
$phase2count=0;
|
455
|
|
456
|
foreach (config_get_path('ipsec/phase2') as $ph2ent) {
|
457
|
if ($ph2ent['ikeid'] != $ph1ent['ikeid']) {
|
458
|
continue;
|
459
|
}
|
460
|
$phase2count++;
|
461
|
}
|
462
|
$fr_prefix = "frp2{$i}";
|
463
|
$fr_header = $fr_prefix . "header";
|
464
|
?>
|
465
|
<button class="btn btn-info" type="button" onclick="show_phase2('tdph2-<?=$i?>','shph2but-<?=$i?>')" value="+"><i class="fa-solid fa-plus-circle"></i> <?php printf(gettext("Show Phase 2 Entries (%s)"), $phase2count); ?></button>
|
466
|
</div>
|
467
|
<div id="tdph2-<?=$i?>" <?=($tdph2_visible != '1' ? 'style="display:none"' : '')?>>
|
468
|
<table class="table table-striped table-hover">
|
469
|
<thead>
|
470
|
<tr>
|
471
|
<th> </th>
|
472
|
<th> </th>
|
473
|
<th><?=gettext("ID"); ?></th>
|
474
|
<th><?=gettext("Mode"); ?></th>
|
475
|
<th><?=gettext("Local Subnet"); ?></th>
|
476
|
<th><?=gettext("Remote Subnet"); ?></th>
|
477
|
<th><?=gettext("P2 Protocol"); ?></th>
|
478
|
<th><?=gettext("P2 Transforms"); ?></th>
|
479
|
<th><?=gettext("P2 Auth Methods"); ?></th>
|
480
|
<th><?=gettext("Description"); ?></th>
|
481
|
<th><?=gettext("P2 actions")?></th>
|
482
|
</tr>
|
483
|
</thead>
|
484
|
<tbody class="p2-entries">
|
485
|
<?php $j = 0; foreach (config_get_path('ipsec/phase2') as $ph2index => $ph2ent): ?>
|
486
|
<?php
|
487
|
if ($ph2ent['ikeid'] != $ph1ent['ikeid']) {
|
488
|
continue;
|
489
|
}
|
490
|
|
491
|
$fr_c = $fr_prefix . "c" . $j;
|
492
|
$fr_d = $fr_prefix . "d" . $j;
|
493
|
|
494
|
$iconfn = "pass";
|
495
|
$entryStatus = (isset($ph2ent['disabled']) || isset($ph1ent['disabled']) ? 'disabled' : 'enabled');
|
496
|
|
497
|
if ($entryStatus == 'disabled') {
|
498
|
$iconfn .= "_d";
|
499
|
}
|
500
|
?>
|
501
|
<tr id="<?=$fr_prefix . $j?>" ondblclick="document.location='vpn_ipsec_phase2.php?p2index=<?=$ph2ent['uniqid']?>'" class="<?= $entryStatus ?>">
|
502
|
<td>
|
503
|
<input type="checkbox" id="<?=$fr_c?>" name="p2entry[]" value="<?=$ph2index?>" onclick="fr_bgcolor('<?=$j?>', '<?=$fr_prefix?>')" />
|
504
|
<button class="fa-solid fa-anchor button-icon" type="submit" name="movep2_<?=$j?>" value="movep2_<?=$j?>" title="<?=gettext("Move checked P2s here")?>"></button>
|
505
|
</td>
|
506
|
<td>
|
507
|
<button value="togglep2_<?=$ph2index?>" name="togglep2_<?=$ph2index?>" title="<?=gettext("click to toggle enabled/disabled status")?>" class="btn btn-xs btn-<?= ($entryStatus == 'disabled'? 'success' : 'warning') ?>" type="submit"><?= ($entryStatus == 'disabled'? 'Enable' : 'Disable') ?></button>
|
508
|
</td>
|
509
|
<td>
|
510
|
<?= htmlspecialchars($ph2ent['reqid']) ?>
|
511
|
</td>
|
512
|
<td id="<?=$fr_d?>" onclick="fr_toggle('<?=$j?>', '<?=$fr_prefix?>')">
|
513
|
<?=$ph2ent['mode']?>
|
514
|
</td>
|
515
|
<?php if (($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == "tunnel6") or ($ph2ent['mode'] == "vti")): ?>
|
516
|
<td id="<?=$fr_d?>" onclick="fr_toggle('<?=$j?>', '<?=$fr_prefix?>')">
|
517
|
<?php if ($show_alias_popup && !empty($ph2ent['localid']) && array_key_exists($ph2ent['localid']['type'], $ipsec_specialnet)): ?>
|
518
|
<a data-toggle="popover" data-trigger="hover focus" title="<?=gettext('Subnet details')?>" data-content="<?=ipsec_idinfo_to_cidr($ph2ent['localid'], false, $ph2ent['mode'])?>" data-html="true">
|
519
|
<?=str_replace('_', '_<wbr>', htmlspecialchars($ipsec_specialnet[$ph2ent['localid']['type']]))?>
|
520
|
</a>
|
521
|
<?php else: ?>
|
522
|
<?=ipsec_idinfo_to_text($ph2ent['localid']); ?>
|
523
|
<?php endif; ?>
|
524
|
</td>
|
525
|
<td id="<?=$fr_d?>" onclick="fr_toggle('<?=$j?>', '<?=$fr_prefix?>')">
|
526
|
<?=ipsec_idinfo_to_text($ph2ent['remoteid']); ?>
|
527
|
</td>
|
528
|
<?php else: ?>
|
529
|
<td colspan="2"></td>
|
530
|
<?php endif; ?>
|
531
|
<td id="<?=$fr_d?>" onclick="fr_toggle('<?=$j?>', '<?=$fr_prefix?>')">
|
532
|
<?=$p2_protos[$ph2ent['protocol']]; ?>
|
533
|
</td>
|
534
|
<td id="<?=$fr_d?>" onclick="fr_toggle('<?=$j?>', '<?=$fr_prefix?>')">
|
535
|
<?php
|
536
|
foreach ($ph2ent['encryption-algorithm-option'] as $k => $ph2ea) {
|
537
|
if ($k) {
|
538
|
echo ", ";
|
539
|
}
|
540
|
echo $p2_ealgos[$ph2ea['name']]['name'];
|
541
|
if ($ph2ea['keylen']) {
|
542
|
if ($ph2ea['keylen'] == "auto") {
|
543
|
echo " (" . gettext("auto") . ")";
|
544
|
} else {
|
545
|
echo " ({$ph2ea['keylen']} " . gettext("bits") . ")";
|
546
|
}
|
547
|
}
|
548
|
}
|
549
|
?>
|
550
|
</td>
|
551
|
<td id="<?=$fr_d?>" onclick="fr_toggle('<?=$j?>', '<?=$fr_prefix?>')">
|
552
|
<?php
|
553
|
if (!empty($ph2ent['hash-algorithm-option']) && is_array($ph2ent['hash-algorithm-option'])) {
|
554
|
foreach ($ph2ent['hash-algorithm-option'] as $k => $ph2ha) {
|
555
|
if ($k) {
|
556
|
echo ", ";
|
557
|
}
|
558
|
echo $p2_halgos[$ph2ha];
|
559
|
}
|
560
|
}
|
561
|
?>
|
562
|
<td><?= htmlspecialchars($ph2ent['descr']) ?></td>
|
563
|
</td>
|
564
|
<td style="cursor: pointer;">
|
565
|
<!-- <button class="fa-solid fa-anchor button-icon" type="submit" name="movep2_<?=$j?>" value="movep2_<?=$j?>" title="<?=gettext("Move checked P2s here")?>"></button> -->
|
566
|
<a class="fa-solid fa-pencil" href="vpn_ipsec_phase2.php?p2index=<?=$ph2ent['uniqid']?>" title="<?=gettext("Edit phase 2 entry"); ?>"></a>
|
567
|
<a class="fa-regular fa-clone" href="vpn_ipsec_phase2.php?dup=<?=$ph2ent['uniqid']?>" title="<?=gettext("Add a new Phase 2 based on this one"); ?>"></a>
|
568
|
<a class="fa-solid fa-trash-can no-confirm" id="Xdelp2_<?=$ph2index?>" title="<?=gettext('Delete phase 2 entry'); ?>"></a>
|
569
|
<button style="display: none;" class="btn btn-xs btn-warning" type="submit" id="delp2_<?=$ph2index?>" name="delp2_<?=$ph2index?>" value="delp2_<?=$ph2index?>" title="<?=gettext('delete phase2 entry'); ?>">delete</button>
|
570
|
</td>
|
571
|
</tr>
|
572
|
<?php $j++; endforeach; ?>
|
573
|
<tr>
|
574
|
<td></td>
|
575
|
<td>
|
576
|
<a class="btn btn-xs btn-success" href="vpn_ipsec_phase2.php?ikeid=<?=$ph1ent['ikeid']?><?php if (isset($ph1ent['mobile'])) echo "&mobile=true"?>">
|
577
|
<i class="fa-solid fa-plus icon-embed-btn"></i>
|
578
|
<?=gettext("Add P2")?>
|
579
|
</a>
|
580
|
</td>
|
581
|
<td colspan="9"></td>
|
582
|
</tr>
|
583
|
</tbody>
|
584
|
</table>
|
585
|
</div>
|
586
|
</td>
|
587
|
</tr>
|
588
|
<?php
|
589
|
$i++;
|
590
|
endforeach; // $a_phase1 as $ph1ent
|
591
|
?>
|
592
|
</tbody>
|
593
|
</table>
|
594
|
</div>
|
595
|
</div>
|
596
|
|
597
|
<nav class="action-buttons">
|
598
|
<?php
|
599
|
/*
|
600
|
if ($i !== 0): ?>
|
601
|
<input type="submit" name="move_<?=$i?>" class="btn btn-default" value="<?=gettext("move selected phase1 entries to end")?>" />
|
602
|
<?php endif;
|
603
|
*/
|
604
|
?>
|
605
|
<a href="vpn_ipsec_phase1.php" class="btn btn-success btn-sm" usepost>
|
606
|
<i class="fa-solid fa-plus icon-embed-btn"></i>
|
607
|
<?=gettext("Add P1")?>
|
608
|
</a>
|
609
|
<?php if ($i !== 0): ?>
|
610
|
<button type="submit" name="del" class="btn btn-danger btn-sm" value="<?=gettext("Delete selected P1s")?>">
|
611
|
<i class="fa-solid fa-trash-can icon-embed-btn"></i>
|
612
|
<?=gettext("Delete P1s")?>
|
613
|
</button>
|
614
|
<?php endif; ?>
|
615
|
</nav>
|
616
|
</form>
|
617
|
|
618
|
<div class="infoblock">
|
619
|
<?php print_info_box(sprintf(gettext('The IPsec status can be checked at %1$s%2$s%3$s.'), '<a href="status_ipsec.php">', gettext("Status:IPsec"), '</a>') . '<br />' .
|
620
|
sprintf(gettext('IPsec debug mode can be enabled at %1$s%2$s%3$s.'), '<a href="vpn_ipsec_settings.php">', gettext("VPN:IPsec:Advanced Settings"), '</a>') . '<br />' .
|
621
|
sprintf(gettext('IPsec can be set to prefer older SAs at %1$s%2$s%3$s.'), '<a href="vpn_ipsec_settings.php">', gettext("VPN:IPsec:Advanced Settings"), '</a>'), 'info', false); ?>
|
622
|
</div>
|
623
|
|
624
|
<script type="text/javascript">
|
625
|
//<![CDATA[
|
626
|
function show_phase2(id, buttonid) {
|
627
|
document.getElementById(buttonid).innerHTML='';
|
628
|
document.getElementById(id).style.display = "block";
|
629
|
var visible = id + '-visible';
|
630
|
document.getElementById(visible).value = "1";
|
631
|
}
|
632
|
|
633
|
events.push(function() {
|
634
|
$('[id^=Xmove_]').click(function (event) {
|
635
|
// ToDo: We POST shift="yes" if the user has the shift key depressed, but that is not yet used
|
636
|
// by the $_POST code. It is intended to allow the user to choose to move stuff to the row before or
|
637
|
// after the clicked anchor icon
|
638
|
if (event.shiftKey) {
|
639
|
$('form').append('<input type="hidden" id="shift" name="shift" value="yes" />');
|
640
|
}
|
641
|
|
642
|
$('#' + event.target.id.slice(1)).click();
|
643
|
});
|
644
|
|
645
|
$('[id^=Xdel_]').click(function (event) {
|
646
|
if (confirm("<?=gettext('Confirmation required to delete this P1 entry.')?>")) {
|
647
|
$('#' + event.target.id.slice(1)).click();
|
648
|
}
|
649
|
});
|
650
|
|
651
|
$('[id^=Xdelp2_]').click(function (event) {
|
652
|
if (confirm("<?=gettext('Confirmation required to delete this P2 entry.')?>")) {
|
653
|
$('#' + event.target.id.slice(1)).click();
|
654
|
}
|
655
|
});
|
656
|
});
|
657
|
//]]>
|
658
|
</script>
|
659
|
|
660
|
<?php
|
661
|
include("foot.inc");
|