Project

General

Profile

Feature #2456 » ipsec.widget.php

Chris Baker, 04/08/2017 01:58 PM

 
<?php
/*
* ipsec.widget.php
*
* part of pfSense (https://www.pfsense.org)
* Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
* Copyright (c) 2004-2005 T. Lechat <dev@lechat.org> (BSD 2 clause)
* Copyright (c) 2007 Jonathan Watt <jwatt@jwatt.org> (BSD 2 clause)
* Copyright (c) 2007 Scott Dale (BSD 2 clause)
* All rights reserved.
*
* originally part of m0n0wall (http://m0n0.ch/wall)
* Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* "This product includes software developed by the pfSense Project
* for use in the pfSense® software distribution. (http://www.pfsense.org/).
*
* 4. The names "pfSense" and "pfSense Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* coreteam@pfsense.org.
*
* 5. Products derived from this software may not be called "pfSense"
* nor may "pfSense" appear in their names without prior written
* permission of the Electric Sheep Fencing, LLC.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
*
* "This product includes software developed by the pfSense Project
* for use in the pfSense software distribution (http://www.pfsense.org/).
*
* THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

$nocsrf = true;

require_once("guiconfig.inc");
require_once("functions.inc");
require_once("ipsec.inc");

// Compose the table contents and pass it back to the ajax caller
if ($_REQUEST && $_REQUEST['ajax']) {

if (isset($config['ipsec']['phase1'])) {
$spd = ipsec_dump_spd();
$sad = ipsec_dump_sad();
$mobile = ipsec_dump_mobile();
$ipsec_status = ipsec_list_sa();

$activecounter = 0;
$inactivecounter = 0;

$ipsec_detail_array = array();
$ikenum = array();
if (isset($config['ipsec']['phase2'])) {
foreach ($config['ipsec']['phase2'] as $ph2ent) {
if (!ipsec_lookup_phase1($ph2ent,$ph1ent)) {
continue;
}

if ($ph2ent['remoteid']['type'] == "mobile" || isset($ph1ent['mobile'])) {
continue;
}

if (isset($ph1ent['disabled']) || isset($ph2ent['disabled'])) {
continue;
}

if (empty($ph1ent['iketype']) || $ph1ent['iketype'] == 'ikev1') {
if (!isset($ikenum[$ph1ent['ikeid']])) {
$ikenum[$ph1ent['ikeid']] = 0;
} else {
$ikenum[$ph1ent['ikeid']]++;
}

$ikeid = "con{$ph1ent['ikeid']}00" . $ikenum[$ph1ent['ikeid']];
} else {
if (isset($ikenum[$ph1ent['ikeid']])) {
continue;
}

$ikeid = "con{$ph1ent['ikeid']}";
$ikenum[$ph1ent['ikeid']] = true;
}

$found = false;
foreach ($ipsec_status as $id => $ikesa) {
if (isset($ikesa['child-sas'])) {
foreach ($ikesa['child-sas'] as $childid => $childsa) {
if ($ikeid == $childid) {
$found = true;
break;
}
}
} else if ($ikeid == $id) {
$found = true;
}

if ($found === true) {
if ($ikesa['state'] == 'ESTABLISHED') {
/* tunnel is up */
$iconfn = "true";
$activecounter++;
} else {
/* tunnel is down */
$iconfn = "false";
$inactivecounter++;
}
break;
}
}

if ($found === false) {
/* tunnel is down */
$iconfn = "false";
$inactivecounter++;
}

$ipsec_detail_array[] = array('src' => convert_friendly_interface_to_friendly_descr($ph1ent['interface']),
'dest' => $ph1ent['remote-gateway'],
'remote-subnet' => ipsec_idinfo_to_text($ph2ent['remoteid']),
'descr' => $ph2ent['descr'],
'status' => $iconfn);
}
}
unset($ikenum);
}

// Only generate the data for the tab that is currently being viewed
switch ($_REQUEST['tab']) {
case "Overview" :
print(" <tr>\n");
print( "<td>" . $activecounter . "</td>\n");
print( "<td>" . $inactivecounter . "</td>\n");
print( "<td>" . (is_array($mobile['pool']) ? htmlspecialchars($mobile['pool'][0]['usage']) : '0') . "</td>\n");
print( "</tr>\n");
break;

case "tunnel" :
foreach ($ipsec_detail_array as $ipsec) {
print(" <tr>\n");
print( "<td>" . htmlspecialchars($ipsec['src']) . "</td>\n");
print( "<td>" . $ipsec['remote-subnet'] . "<br />(" . htmlspecialchars($ipsec['dest']) . ")</td>\n");
print( "<td>" . htmlspecialchars($ipsec['descr']) . "</td>\n");

if ($ipsec['status'] == "true") {
print('<td><i class="fa fa-arrow-up text-success"></i></td>' . "\n");
} else {
print('<td><i class="fa fa-arrow-down text-danger"></i></td>' . "\n");
}

print( "</tr>\n");
}
break;

case "mobile" :
if (!is_array($mobile['pool'])) {
break;
}
foreach ($mobile['pool'] as $pool) {
if (!is_array($pool['lease'])) {
continue;
}

foreach ($pool['lease'] as $muser) {
print(" <tr>\n");
print( "<td>" . htmlspecialchars($muser['id']) . "</td>\n");
print( "<td>" . htmlspecialchars($muser['host']) . "</td>\n");
print( "<td>" . htmlspecialchars($muser['status']) . "</td>\n");
print(" </tr>\n");
}
}
break;
}

exit;
}

if ($_POST) {

if (!is_array($user_settings["widgets"]["ipsec_widget"])) {
$user_settings["widgets"]["ipsec_widget"] = array();
}
if (isset($_POST["newdefaulttab6"])) {
$user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"] = $_POST["newdefaulttab6"];
}
save_widget_settings($_SESSION['Username'], $user_settings["widgets"], gettext("Updated gateways widget settings via dashboard."));
header("Location: /");
exit(0);
}
$NewDefaultTab = $user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"];
$TunnelDefault = false;
$OverviewDefault = false;
$MobileDefault = false;
$TunnelDisplay ="none";
$OverviewDisplay ="none";
$MobileDisplay ="none";

switch($NewDefaultTab) {
case "Overview" :
$OverviewDefault = true;
$OverviewDisplay = "block";
break;
case "tunnel" :
$TunnelDefault = true;
$TunnelDisplay = "block";
break;
case "mobile" :
$MobileDefault = true;
$MobileDisplay = "block";
break;
}

if (isset($config['ipsec']['phase1'])) {
$tab_array = array();
$tab_array[] = array(gettext("Overview"), $OverviewDefault, "ipsec-Overview");
$tab_array[] = array(gettext("Tunnels"), $TunnelDefault, "ipsec-tunnel");
$tab_array[] = array(gettext("Mobile"), $MobileDefault, "ipsec-mobile");

display_widget_tabs($tab_array);
}

$mobile = ipsec_dump_mobile();
$widgetperiod = isset($config['widgets']['period']) ? $config['widgets']['period'] * 1000 : 10000;

if (isset($config['ipsec']['phase2'])): ?>
<div id="ipsec-Overview" style="display:<?=$OverviewDisplay;?>;" class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th><?=gettext("Active Tunnels")?></th>
<th><?=gettext("Inactive Tunnels")?></th>
<th><?=gettext("Mobile Users")?></th>
</tr>
</thead>
<tbody>
<tr><td colspan="3"><?=gettext("Retrieving overview data ")?><i class="fa fa-cog fa-spin"></i></td></tr>
</tbody>
</table>
</div>
<div class="table-responsive" id="ipsec-tunnel" style="display:<?=$TunnelDisplay;?>;">
<table class="table table-striped table-hover">
<thead>
<tr>
<th><?=gettext("Source")?></th>
<th><?=gettext("Destination")?></th>
<th><?=gettext("Description")?></th>
<th><?=gettext("Status")?></th>
</tr>
</thead>
<tbody>
<tr><td colspan="4"><?=gettext("Retrieving tunnel data ")?><i class="fa fa-cog fa-spin"></i></td></tr>
</tbody>
</table>
</div>

<?php if (is_array($mobile['pool'])): ?>
<div id="ipsec-mobile" style="display:<?=$MobileDisplay;?>;" class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th><?=gettext("User")?></th>
<th><?=gettext("IP")?></th>
<th><?=gettext("Status")?></th>
</tr>
</thead>
<tbody>
<tr><td colspan="3"><?=gettext("Retrieving mobile data ")?><i class="fa fa-cog fa-spin"></i></td></tr>
</tbody>
</table>
</div>
<?php endif;?>
<?php else: ?>
<div>
<h5 style="padding-left:10px;"><?=gettext("There are no configured IPsec Tunnels")?></h5>
<p style="padding-left:10px;"><?=gettext('IPsec can be configured <a href="vpn_ipsec.php">here</a>.')?></p>
</div>
<?php endif;

// This function was in index.php It seems that the ipsec widget is the only place it is used
// so now it lives here. It wouldn't hurt to update this function and the tab display, but it
// looks OK for now. The display_widget_tabs() function in guiconfig.inc would need to be updated to match
?>
<div id="widget-<?=$widgetname?>_panel-footer" class="panel-footer collapse">
<input type="hidden" id="ipsec-config" name="ipsec-config" value="" />
<div id="ipsec-settings" class="widgetconfigdiv" >
<form action="/widgets/widgets/ipsec.widget.php" method="post" name="ipsec_widget_iform" id="ipsec_widget_iform">
Display:

<select class="form-control" id="newdefaulttab6" name="newdefaulttab6">
<?php
if($user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"] === "Overview") {
echo '<option value="Overview" selected>Overview</option>';
echo '<option value="tunnel">tunnel</option>';
echo '<option value="mobile">mobile</option>';
} elseif ($user_settings["widgets"]["ipsec_widget"]["newdefaulttab6"] === "tunnel") {
echo '<option value="Overview">Overview</option>';
echo '<option value="tunnel" selected>tunnel</option>';
echo '<option value="mobile">mobile</option>';
} else {
echo '<option value="Overview">Overview</option>';
echo '<option value="tunnel">tunnel</option>';
echo '<option value="mobile" selected>mobile</option>';
}
?>
</select>

<button id="submit_settings" name="submit_settings" type="submit" onclick="return updatePref();" class="btn btn-primary btn-sm" value="<?=gettext('Save Settings')?>">
<i class="fa fa-save icon-embed-btn"></i>
<?=gettext('Save Settings')?>
</button>


</form>
</div>
</div>

<script type="text/javascript">
//<![CDATA[
var els = document.querySelectorAll("a[href='#widget-ipsec_panel-footer']");
for (var i = 0, l = els.length; i < l; i++) {
var el = els[i];
el.className = el.className.replace("hidden", "").trim()
}
curtab = "<?=$NewDefaultTab;?>";
function changeTabDIV(selectedDiv) {
var dashpos = selectedDiv.indexOf("-");
var tabclass = selectedDiv.substring(0, dashpos);
curtab = selectedDiv.substring(dashpos+1, 20);
d = document;

//get deactive tabs first
tabclass = tabclass + "-class-tabdeactive";

var tabs = document.getElementsByClassName(tabclass);
var incTabSelected = selectedDiv + "-deactive";

for (i = 0; i < tabs.length; i++) {
var tab = tabs[i].id;
dashpos = tab.lastIndexOf("-");
var tab2 = tab.substring(0, dashpos) + "-deactive";

if (tab2 == incTabSelected) {
tablink = d.getElementById(tab2);
tablink.style.display = "none";
tab2 = tab.substring(0, dashpos) + "-active";
tablink = d.getElementById(tab2);
tablink.style.display = "table-cell";

//now show main div associated with link clicked
tabmain = d.getElementById(selectedDiv);
tabmain.style.display = "block";
} else {
tab2 = tab.substring(0, dashpos) + "-deactive";
tablink = d.getElementById(tab2);
tablink.style.display = "table-cell";
tab2 = tab.substring(0, dashpos) + "-active";
tablink = d.getElementById(tab2);
tablink.style.display = "none";

//hide sections we don't want to see
tab2 = tab.substring(0, dashpos);
tabmain = d.getElementById(tab2);
tabmain.style.display = "none";
}
}
}
function get_ipsec_stats() {
var ajaxRequest;

ajaxRequest = $.ajax({
url: "/widgets/widgets/ipsec.widget.php",
type: "post",
data: {
ajax: "ajax",
tab: curtab
}
});

// Deal with the results of the above ajax call
ajaxRequest.done(function (response, textStatus, jqXHR) {

$('tbody', '#ipsec-' + curtab).html(response);

// and do it again
setTimeout(get_ipsec_stats, "<?=$widgetperiod?>");
});
}
events.push(function(){
// Start polling for updates some small random number of seconds from now (so that all the widgets don't
// hit the server at exactly the same time)
setTimeout(get_ipsec_stats, Math.floor((Math.random() * 10000) + 1000));
});
//]]>
</script>

(2-2/2)