1
|
<?php
|
2
|
/*
|
3
|
* ipsec.widget.php
|
4
|
*
|
5
|
* part of pfSense (https://www.pfsense.org)
|
6
|
* Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
|
7
|
* Copyright (c) 2004-2005 T. Lechat <dev@lechat.org> (BSD 2 clause)
|
8
|
* Copyright (c) 2007 Jonathan Watt <jwatt@jwatt.org> (BSD 2 clause)
|
9
|
* Copyright (c) 2007 Scott Dale (BSD 2 clause)
|
10
|
* All rights reserved.
|
11
|
*
|
12
|
* originally part of m0n0wall (http://m0n0.ch/wall)
|
13
|
* Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
|
14
|
* All rights reserved.
|
15
|
*
|
16
|
* Redistribution and use in source and binary forms, with or without
|
17
|
* modification, are permitted provided that the following conditions are met:
|
18
|
*
|
19
|
* 1. Redistributions of source code must retain the above copyright notice,
|
20
|
* this list of conditions and the following disclaimer.
|
21
|
*
|
22
|
* 2. Redistributions in binary form must reproduce the above copyright
|
23
|
* notice, this list of conditions and the following disclaimer in
|
24
|
* the documentation and/or other materials provided with the
|
25
|
* distribution.
|
26
|
*
|
27
|
* 3. All advertising materials mentioning features or use of this software
|
28
|
* must display the following acknowledgment:
|
29
|
* "This product includes software developed by the pfSense Project
|
30
|
* for use in the pfSense® software distribution. (http://www.pfsense.org/).
|
31
|
*
|
32
|
* 4. The names "pfSense" and "pfSense Project" must not be used to
|
33
|
* endorse or promote products derived from this software without
|
34
|
* prior written permission. For written permission, please contact
|
35
|
* coreteam@pfsense.org.
|
36
|
*
|
37
|
* 5. Products derived from this software may not be called "pfSense"
|
38
|
* nor may "pfSense" appear in their names without prior written
|
39
|
* permission of the Electric Sheep Fencing, LLC.
|
40
|
*
|
41
|
* 6. Redistributions of any form whatsoever must retain the following
|
42
|
* acknowledgment:
|
43
|
*
|
44
|
* "This product includes software developed by the pfSense Project
|
45
|
* for use in the pfSense software distribution (http://www.pfsense.org/).
|
46
|
*
|
47
|
* THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
|
48
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
49
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
50
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
|
51
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
52
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
53
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
54
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
55
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
56
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
57
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
58
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
59
|
*/
|
60
|
|
61
|
$nocsrf = true;
|
62
|
|
63
|
require_once("guiconfig.inc");
|
64
|
require_once("functions.inc");
|
65
|
require_once("ipsec.inc");
|
66
|
|
67
|
// Compose the table contents and pass it back to the ajax caller
|
68
|
if ($_REQUEST && $_REQUEST['ajax']) {
|
69
|
|
70
|
if (isset($config['ipsec']['phase1'])) {
|
71
|
$spd = ipsec_dump_spd();
|
72
|
$sad = ipsec_dump_sad();
|
73
|
$mobile = ipsec_dump_mobile();
|
74
|
$ipsec_status = ipsec_list_sa();
|
75
|
|
76
|
$activecounter = 0;
|
77
|
$inactivecounter = 0;
|
78
|
|
79
|
$ipsec_detail_array = array();
|
80
|
$ikenum = array();
|
81
|
if (isset($config['ipsec']['phase2'])) {
|
82
|
foreach ($config['ipsec']['phase2'] as $ph2ent) {
|
83
|
if (!ipsec_lookup_phase1($ph2ent,$ph1ent)) {
|
84
|
continue;
|
85
|
}
|
86
|
|
87
|
if ($ph2ent['remoteid']['type'] == "mobile" || isset($ph1ent['mobile'])) {
|
88
|
continue;
|
89
|
}
|
90
|
|
91
|
if (isset($ph1ent['disabled']) || isset($ph2ent['disabled'])) {
|
92
|
continue;
|
93
|
}
|
94
|
|
95
|
if (empty($ph1ent['iketype']) || $ph1ent['iketype'] == 'ikev1') {
|
96
|
if (!isset($ikenum[$ph1ent['ikeid']])) {
|
97
|
$ikenum[$ph1ent['ikeid']] = 0;
|
98
|
} else {
|
99
|
$ikenum[$ph1ent['ikeid']]++;
|
100
|
}
|
101
|
|
102
|
$ikeid = "con{$ph1ent['ikeid']}00" . $ikenum[$ph1ent['ikeid']];
|
103
|
} else {
|
104
|
if (isset($ikenum[$ph1ent['ikeid']])) {
|
105
|
continue;
|
106
|
}
|
107
|
|
108
|
$ikeid = "con{$ph1ent['ikeid']}";
|
109
|
$ikenum[$ph1ent['ikeid']] = true;
|
110
|
}
|
111
|
|
112
|
$found = false;
|
113
|
foreach ($ipsec_status as $id => $ikesa) {
|
114
|
if (isset($ikesa['child-sas'])) {
|
115
|
foreach ($ikesa['child-sas'] as $childid => $childsa) {
|
116
|
if ($ikeid == $childid) {
|
117
|
$found = true;
|
118
|
break;
|
119
|
}
|
120
|
}
|
121
|
} else if ($ikeid == $id) {
|
122
|
$found = true;
|
123
|
}
|
124
|
|
125
|
if ($found === true) {
|
126
|
if ($ikesa['state'] == 'ESTABLISHED') {
|
127
|
/* tunnel is up */
|
128
|
$iconfn = "true";
|
129
|
$activecounter++;
|
130
|
} else {
|
131
|
/* tunnel is down */
|
132
|
$iconfn = "false";
|
133
|
$inactivecounter++;
|
134
|
}
|
135
|
break;
|
136
|
}
|
137
|
}
|
138
|
|
139
|
if ($found === false) {
|
140
|
/* tunnel is down */
|
141
|
$iconfn = "false";
|
142
|
$inactivecounter++;
|
143
|
}
|
144
|
|
145
|
$ipsec_detail_array[] = array('src' => convert_friendly_interface_to_friendly_descr($ph1ent['interface']),
|
146
|
'dest' => $ph1ent['remote-gateway'],
|
147
|
'remote-subnet' => ipsec_idinfo_to_text($ph2ent['remoteid']),
|
148
|
'descr' => $ph2ent['descr'],
|
149
|
'status' => $iconfn);
|
150
|
}
|
151
|
}
|
152
|
unset($ikenum);
|
153
|
}
|
154
|
|
155
|
// Only generate the data for the tab that is currently being viewed
|
156
|
switch ($_REQUEST['tab']) {
|
157
|
case "Overview" :
|
158
|
print(" <tr>\n");
|
159
|
print( "<td>" . $activecounter . "</td>\n");
|
160
|
print( "<td>" . $inactivecounter . "</td>\n");
|
161
|
print( "<td>" . (is_array($mobile['pool']) ? htmlspecialchars($mobile['pool'][0]['usage']) : '0') . "</td>\n");
|
162
|
print( "</tr>\n");
|
163
|
break;
|
164
|
|
165
|
case "tunnel" :
|
166
|
foreach ($ipsec_detail_array as $ipsec) {
|
167
|
print(" <tr>\n");
|
168
|
print( "<td>" . htmlspecialchars($ipsec['src']) . "</td>\n");
|
169
|
print( "<td>" . $ipsec['remote-subnet'] . "<br />(" . htmlspecialchars($ipsec['dest']) . ")</td>\n");
|
170
|
print( "<td>" . htmlspecialchars($ipsec['descr']) . "</td>\n");
|
171
|
|
172
|
if ($ipsec['status'] == "true") {
|
173
|
print('<td><i class="fa fa-arrow-up text-success"></i></td>' . "\n");
|
174
|
} else {
|
175
|
print('<td><i class="fa fa-arrow-down text-danger"></i></td>' . "\n");
|
176
|
}
|
177
|
|
178
|
print( "</tr>\n");
|
179
|
}
|
180
|
break;
|
181
|
|
182
|
case "mobile" :
|
183
|
if (!is_array($mobile['pool'])) {
|
184
|
break;
|
185
|
}
|
186
|
foreach ($mobile['pool'] as $pool) {
|
187
|
if (!is_array($pool['lease'])) {
|
188
|
continue;
|
189
|
}
|
190
|
|
191
|
foreach ($pool['lease'] as $muser) {
|
192
|
print(" <tr>\n");
|
193
|
print( "<td>" . htmlspecialchars($muser['id']) . "</td>\n");
|
194
|
print( "<td>" . htmlspecialchars($muser['host']) . "</td>\n");
|
195
|
print( "<td>" . htmlspecialchars($muser['status']) . "</td>\n");
|
196
|
print(" </tr>\n");
|
197
|
}
|
198
|
}
|
199
|
break;
|
200
|
}
|
201
|
|
202
|
exit;
|
203
|
}
|
204
|
|
205
|
if ($_POST) {
|
206
|
|
207
|
if (!is_array($user_settings["widgets"]["ipsec_widget"])) {
|
208
|
$user_settings["widgets"]["ipsec_widget"] = array();
|
209
|
}
|
210
|
if (isset($_POST["newdefaulttab6"])) {
|
211
|
$user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"] = $_POST["newdefaulttab6"];
|
212
|
}
|
213
|
save_widget_settings($_SESSION['Username'], $user_settings["widgets"], gettext("Updated gateways widget settings via dashboard."));
|
214
|
header("Location: /");
|
215
|
exit(0);
|
216
|
}
|
217
|
$NewDefaultTab = $user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"];
|
218
|
$TunnelDefault = false;
|
219
|
$OverviewDefault = false;
|
220
|
$MobileDefault = false;
|
221
|
$TunnelDisplay ="none";
|
222
|
$OverviewDisplay ="none";
|
223
|
$MobileDisplay ="none";
|
224
|
|
225
|
switch($NewDefaultTab) {
|
226
|
case "Overview" :
|
227
|
$OverviewDefault = true;
|
228
|
$OverviewDisplay = "block";
|
229
|
break;
|
230
|
case "tunnel" :
|
231
|
$TunnelDefault = true;
|
232
|
$TunnelDisplay = "block";
|
233
|
break;
|
234
|
case "mobile" :
|
235
|
$MobileDefault = true;
|
236
|
$MobileDisplay = "block";
|
237
|
break;
|
238
|
}
|
239
|
|
240
|
if (isset($config['ipsec']['phase1'])) {
|
241
|
$tab_array = array();
|
242
|
$tab_array[] = array(gettext("Overview"), $OverviewDefault, "ipsec-Overview");
|
243
|
$tab_array[] = array(gettext("Tunnels"), $TunnelDefault, "ipsec-tunnel");
|
244
|
$tab_array[] = array(gettext("Mobile"), $MobileDefault, "ipsec-mobile");
|
245
|
|
246
|
display_widget_tabs($tab_array);
|
247
|
}
|
248
|
|
249
|
$mobile = ipsec_dump_mobile();
|
250
|
$widgetperiod = isset($config['widgets']['period']) ? $config['widgets']['period'] * 1000 : 10000;
|
251
|
|
252
|
if (isset($config['ipsec']['phase2'])): ?>
|
253
|
<div id="ipsec-Overview" style="display:<?=$OverviewDisplay;?>;" class="table-responsive">
|
254
|
<table class="table table-striped table-hover">
|
255
|
<thead>
|
256
|
<tr>
|
257
|
<th><?=gettext("Active Tunnels")?></th>
|
258
|
<th><?=gettext("Inactive Tunnels")?></th>
|
259
|
<th><?=gettext("Mobile Users")?></th>
|
260
|
</tr>
|
261
|
</thead>
|
262
|
<tbody>
|
263
|
<tr><td colspan="3"><?=gettext("Retrieving overview data ")?><i class="fa fa-cog fa-spin"></i></td></tr>
|
264
|
</tbody>
|
265
|
</table>
|
266
|
</div>
|
267
|
<div class="table-responsive" id="ipsec-tunnel" style="display:<?=$TunnelDisplay;?>;">
|
268
|
<table class="table table-striped table-hover">
|
269
|
<thead>
|
270
|
<tr>
|
271
|
<th><?=gettext("Source")?></th>
|
272
|
<th><?=gettext("Destination")?></th>
|
273
|
<th><?=gettext("Description")?></th>
|
274
|
<th><?=gettext("Status")?></th>
|
275
|
</tr>
|
276
|
</thead>
|
277
|
<tbody>
|
278
|
<tr><td colspan="4"><?=gettext("Retrieving tunnel data ")?><i class="fa fa-cog fa-spin"></i></td></tr>
|
279
|
</tbody>
|
280
|
</table>
|
281
|
</div>
|
282
|
|
283
|
<?php if (is_array($mobile['pool'])): ?>
|
284
|
<div id="ipsec-mobile" style="display:<?=$MobileDisplay;?>;" class="table-responsive">
|
285
|
<table class="table table-striped table-hover">
|
286
|
<thead>
|
287
|
<tr>
|
288
|
<th><?=gettext("User")?></th>
|
289
|
<th><?=gettext("IP")?></th>
|
290
|
<th><?=gettext("Status")?></th>
|
291
|
</tr>
|
292
|
</thead>
|
293
|
<tbody>
|
294
|
<tr><td colspan="3"><?=gettext("Retrieving mobile data ")?><i class="fa fa-cog fa-spin"></i></td></tr>
|
295
|
</tbody>
|
296
|
</table>
|
297
|
</div>
|
298
|
<?php endif;?>
|
299
|
<?php else: ?>
|
300
|
<div>
|
301
|
<h5 style="padding-left:10px;"><?=gettext("There are no configured IPsec Tunnels")?></h5>
|
302
|
<p style="padding-left:10px;"><?=gettext('IPsec can be configured <a href="vpn_ipsec.php">here</a>.')?></p>
|
303
|
</div>
|
304
|
<?php endif;
|
305
|
|
306
|
// This function was in index.php It seems that the ipsec widget is the only place it is used
|
307
|
// so now it lives here. It wouldn't hurt to update this function and the tab display, but it
|
308
|
// looks OK for now. The display_widget_tabs() function in guiconfig.inc would need to be updated to match
|
309
|
?>
|
310
|
<div id="widget-<?=$widgetname?>_panel-footer" class="panel-footer collapse">
|
311
|
<input type="hidden" id="ipsec-config" name="ipsec-config" value="" />
|
312
|
<div id="ipsec-settings" class="widgetconfigdiv" >
|
313
|
<form action="/widgets/widgets/ipsec.widget.php" method="post" name="ipsec_widget_iform" id="ipsec_widget_iform">
|
314
|
Display:
|
315
|
|
316
|
<select class="form-control" id="newdefaulttab6" name="newdefaulttab6">
|
317
|
<?php
|
318
|
if($user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"] === "Overview") {
|
319
|
echo '<option value="Overview" selected>Overview</option>';
|
320
|
echo '<option value="tunnel">tunnel</option>';
|
321
|
echo '<option value="mobile">mobile</option>';
|
322
|
} elseif ($user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"] === "tunnel") {
|
323
|
echo '<option value="Overview">Overview</option>';
|
324
|
echo '<option value="tunnel" selected>tunnel</option>';
|
325
|
echo '<option value="mobile">mobile</option>';
|
326
|
} else {
|
327
|
echo '<option value="Overview">Overview</option>';
|
328
|
echo '<option value="tunnel">tunnel</option>';
|
329
|
echo '<option value="mobile" selected>mobile</option>';
|
330
|
}
|
331
|
?>
|
332
|
</select>
|
333
|
|
334
|
|
335
|
<button id="submit_settings" name="submit_settings" type="submit" onclick="return updatePref();" class="btn btn-primary btn-sm" value="<?=gettext('Save Settings')?>">
|
336
|
<i class="fa fa-save icon-embed-btn"></i>
|
337
|
<?=gettext('Save Settings')?>
|
338
|
</button>
|
339
|
|
340
|
|
341
|
</form>
|
342
|
</div>
|
343
|
</div>
|
344
|
|
345
|
<script type="text/javascript">
|
346
|
//<![CDATA[
|
347
|
var els = document.querySelectorAll("a[href='#widget-ipsec_panel-footer']");
|
348
|
for (var i = 0, l = els.length; i < l; i++) {
|
349
|
var el = els[i];
|
350
|
el.className = el.className.replace("hidden", "").trim()
|
351
|
}
|
352
|
|
353
|
curtab = "<?=$NewDefaultTab;?>";
|
354
|
function changeTabDIV(selectedDiv) {
|
355
|
var dashpos = selectedDiv.indexOf("-");
|
356
|
var tabclass = selectedDiv.substring(0, dashpos);
|
357
|
curtab = selectedDiv.substring(dashpos+1, 20);
|
358
|
d = document;
|
359
|
|
360
|
//get deactive tabs first
|
361
|
tabclass = tabclass + "-class-tabdeactive";
|
362
|
|
363
|
var tabs = document.getElementsByClassName(tabclass);
|
364
|
var incTabSelected = selectedDiv + "-deactive";
|
365
|
|
366
|
for (i = 0; i < tabs.length; i++) {
|
367
|
var tab = tabs[i].id;
|
368
|
dashpos = tab.lastIndexOf("-");
|
369
|
var tab2 = tab.substring(0, dashpos) + "-deactive";
|
370
|
|
371
|
if (tab2 == incTabSelected) {
|
372
|
tablink = d.getElementById(tab2);
|
373
|
tablink.style.display = "none";
|
374
|
tab2 = tab.substring(0, dashpos) + "-active";
|
375
|
tablink = d.getElementById(tab2);
|
376
|
tablink.style.display = "table-cell";
|
377
|
|
378
|
//now show main div associated with link clicked
|
379
|
tabmain = d.getElementById(selectedDiv);
|
380
|
tabmain.style.display = "block";
|
381
|
} else {
|
382
|
tab2 = tab.substring(0, dashpos) + "-deactive";
|
383
|
tablink = d.getElementById(tab2);
|
384
|
tablink.style.display = "table-cell";
|
385
|
tab2 = tab.substring(0, dashpos) + "-active";
|
386
|
tablink = d.getElementById(tab2);
|
387
|
tablink.style.display = "none";
|
388
|
|
389
|
//hide sections we don't want to see
|
390
|
tab2 = tab.substring(0, dashpos);
|
391
|
tabmain = d.getElementById(tab2);
|
392
|
tabmain.style.display = "none";
|
393
|
}
|
394
|
}
|
395
|
}
|
396
|
function get_ipsec_stats() {
|
397
|
var ajaxRequest;
|
398
|
|
399
|
ajaxRequest = $.ajax({
|
400
|
url: "/widgets/widgets/ipsec.widget.php",
|
401
|
type: "post",
|
402
|
data: {
|
403
|
ajax: "ajax",
|
404
|
tab: curtab
|
405
|
}
|
406
|
});
|
407
|
|
408
|
// Deal with the results of the above ajax call
|
409
|
ajaxRequest.done(function (response, textStatus, jqXHR) {
|
410
|
|
411
|
$('tbody', '#ipsec-' + curtab).html(response);
|
412
|
|
413
|
// and do it again
|
414
|
setTimeout(get_ipsec_stats, "<?=$widgetperiod?>");
|
415
|
});
|
416
|
}
|
417
|
events.push(function(){
|
418
|
// Start polling for updates some small random number of seconds from now (so that all the widgets don't
|
419
|
// hit the server at exactly the same time)
|
420
|
setTimeout(get_ipsec_stats, Math.floor((Math.random() * 10000) + 1000));
|
421
|
});
|
422
|
//]]>
|
423
|
</script>
|
424
|
|