Mitigated possible DoS Vulnerability

pull/15/head
ioClarity 5 years ago
parent d86be0d050
commit 899731f084

1
.gitignore vendored

@ -17,3 +17,4 @@ qnvoice
qnrelay qnrelay
qnmodem qnmodem
My_Hosts.txt My_Hosts.txt
dashboardV2/jsonData/*.json

@ -27,3 +27,25 @@ will want to use a hardened server, like apache, and a different index.php file.
Please note that if you are tryping in a URCALL when the webpage is refreshing, Please note that if you are tryping in a URCALL when the webpage is refreshing,
the entry field will loose focus and you'll have to try again. the entry field will loose focus and you'll have to try again.
#### DASHBOARD V2 ####
A new responsive dashboard built on the Bootstrap 4.5 framework has been
added. If you have configured the dashboard with the commands above you can
access the new dashboard by appending "/dashboardV2" to the URL. For example
http://<hostname>.local/dashboardV2
Notes:
The responsive dashboard currently has the following features
* Page does not have to reload to refresh its data solving the URCall focus issue
* Dashboard refresh is suggested to be set at 10 seconds. Any value less than 8 will
have no effect.
* Mobile design friendly. On smaller screens some columns in the tables will be
hidden, however, simply rotate your mobile device to landscape view and they
should appear
* QnRemote section (aka URCall section) has improved design for mobile device use
Future improvements will be made to
* The layout to respect order of the dash_show_order configuration item
* Misc performance enhancements

@ -0,0 +1,144 @@
<?php
# Load functions and read config file
include '../init.php';
$lastRunFile = "/tmp/lastJsonGen.tmp";
$lastRunTime = filemtime($lastRunFile);
$now = time();
# Only Generage jSon Data if it hasnt been generated in the last 8 seconds
if( ($now-$lastRunTime) > 8 )
{
# OpenDatabase
$dbname = $cfgdir.'/qn.db';
$db = new SQLite3($dbname, SQLITE3_OPEN_READONLY);
# Only proccess if defined in show list
if( in_array("LH", $showlist) ) {
$jsonArray = [];
$ss = 'SELECT callsign,sfx,message,module,reflector,maidenhead,latitude,longitude,strftime("%s","now")-lasttime as lastTime FROM LHEARD ORDER BY lastTime LIMIT '.GetCFGValue('dash_lastheard_count').' ';
if ($stmnt = $db->prepare($ss)) {
if ($result = $stmnt->execute()) {
while ($row = $result->FetchArray(SQLITE3_ASSOC)) {
//transform the lastTimeHeard to a printable string
$row['lastTime'] = SecToString($row['lastTime']);
$row['maidenheadProcessed'] = Maidenhead($row['maidenhead'], $row['latitude'], $row['longitude']);
$row['callsignProcessed'] = MyAndSfxToQrz($row['callsign'], $row['sfx']);
$jsonArray[] = $row;
}
$result->finalize();
}
$stmnt->close();
}
# Write the lastHeard JSON file
$lhJsonFile = fopen("../jsonData/lastHeard.json", "w");
fwrite($lhJsonFile, json_encode($jsonArray));
fclose($lhJsonFile);
} else { echo "Section disabled";
$lhJsonFile = fopen("../jsonData/lastHeard.json", "w");
fwrite($lhJsonFile, "{ }\n");
fclose($lhJsonFile);
}
# Only proccess if defined in show list
if( in_array("MO", $showlist) ) {
$jsonArray = [];
foreach (array('a', 'b', 'c') as $mod) {
$linkstatus = 'Unlinked';
$address = '';
$ctime = '';
$module = 'module_'.$mod;
if (array_key_exists($module, $cfg)) {
$freq = 0.0;
if (array_key_exists($module.'_tx_frequency', $cfg)) {
$freq = $cfg[$module.'_tx_frequency'];
}
else if (array_key_exists($module.'_frequency', $cfg)) {
$freq = $cfg[$module.'_frequency'];
}
$ss = 'SELECT ip_address,to_callsign,to_mod,strftime("%s","now")-linked_time as linkedTime FROM LINKSTATUS WHERE from_mod=' . "'" . strtoupper($mod) . "';";
if ($stmnt = $db->prepare($ss)) {
if ($result = $stmnt->execute()) {
if ($row = $result->FetchArray(SQLITE3_ASSOC)) {
$row['linkedTime'] = SecToString(intval($row['linkedTime']));
$row['module'] = strtoupper($mod);
$row['modem'] = $cfg[$module];
$row['freq'] = $freq;
$row['link'] = $row['to_callsign']." ".$row['to_mod'];
$jsonArray[] = $row;
} else {
$jsonArray[] = array('linkedTime' => '',
'module' =>strtoupper($mod),
'modem' => $cfg[$module],
'freq' => $freq,
'link' => 'Unlinked',
'ip_address' => '',
'to_callsign' => '',
'to_mod' => '');
}
$result->finalize();
}
$stmnt->close();
}
}
}
$modJsonFile = fopen("../jsonData/modules.json", "w");
fwrite($modJsonFile, json_encode($jsonArray));
fclose($modJsonFile);
} else {
$modJsonFile = fopen("../jsonData/modules.json", "w");
fwrite($modJsonFile, "{ }\n");
fclose($modJsonFile);
}
# Close database it is not needed anymore
$db->Close();
# Only proccess if defined in show list
if( in_array("PS", $showlist) ) {
$jsonArray = [];
$lines = explode("\n", `ps -eo user,pid,pcpu,size,cmd | grep -e qngateway -e qnlink -e qndtmf -e qndvap -e qnitap -e qnrelay -e qndvrptr -e qnmodem -e MMDVMHost | grep -v grep`);
foreach ($lines as $line) {
$items = preg_split ('/\s+/', $line, 5);
if( isset( $items[1] ) ) {
$jsonArray[] = array('user' => $items[0],
'pid' => $items[1],
'pcpu' => $items[2],
'size' => $items[3],
'cmd' => $items[4]);
}
}
$psJsonFile = fopen("../jsonData/ps.json", "w");
if ($jsonArray) {
fwrite($psJsonFile, json_encode($jsonArray));
} else {
fwrite($psJsonFile, "{ }\n");
}
fclose($psJsonFile);
} else {
# Section is disabled, replace with blank JSON file
$psJsonFile = fopen("../jsonData/ps.json", "w");
fwrite($psJsonFile, "{ }\n");
fclose($psJsonFile);
}
# Update last run time
`touch $lastRunFile`;
}
# If the jsonFile is in the URL lets get the file
if( isset($_GET['jsonFile']) )
{
if( $_GET['jsonFile'] == "lastHeard" )
readfile("../jsonData/lastHeard.json");
else if( $_GET['jsonFile'] == "modules" )
readfile("../jsonData/modules.json");
else if( $_GET['jsonFile'] == "ps" )
readfile("../jsonData/ps.json");
}
?>

@ -1,23 +1,36 @@
<!DOCTYPE html> <!DOCTYPE html>
<?php <?php
# If visiting this page by /dashboardV2 (no / suffix) it causes issues referring to CSS / JS
# So we check to see the URL and redirect to /dashboardV2/ if we need to
function endsWith($string, $test) {
$strlen = strlen($string);
$testlen = strlen($test);
if ($testlen > $strlen) return false;
return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}
if ( !( endsWith($_SERVER['REQUEST_URI'], "/index.php") || (endsWith($_SERVER['REQUEST_URI'], "/") ) ) )
{
header("Location: dashboardV2/");
}
# Load functions and read config file # Load functions and read config file
include 'init.php'; include 'init.php';
?> ?>
<html lang="en"> <html lang="en">
<head> <head>
<title>QnetGateway Dashboard V2</title> <title>QnetGateway Dashboard V2</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8"> <meta charset="utf-8">
<!-- Bootstrap --> <!-- Bootstrap -->
<link href="dashboardV2/css/bootstrap.min.css" rel="stylesheet" media="screen"> <link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="dashboardV2/css/bootstrap-table.min.css" rel="stylesheet"> <link href="css/bootstrap-table.min.css" rel="stylesheet">
</head> </head>
<body> <body>
<!-- Include jQuery and Bootstrap--> <!-- Include jQuery and Bootstrap-->
<script src="dashboardV2/js/jquery.min.js"></script> <script src="js/jquery.min.js"></script>
<script src="dashboardV2/js/bootstrap.min.js"></script> <script src="js/bootstrap.min.js"></script>
<!-- Header - maybe turn this into a Nav Bar in the future --> <!-- Header - maybe turn this into a Nav Bar in the future -->
<nav class="navbar navbar-light bg-light"> <nav class="navbar navbar-light bg-light">
@ -43,9 +56,9 @@
<table class="table table-sm" <table class="table table-sm"
id="lhTable" id="lhTable"
data-auto-refresh="true" data-auto-refresh="true"
data-auto-refresh-interval="10" data-auto-refresh-interval="<?php echo GetCFGValue('dash_refresh'); ?>"
data-pagination="false" data-pagination="false"
data-url="dashboardV2/jsonData/lastHeard.php" data-url="bin/getJson.php?jsonFile=lastHeard"
data-check-on-init="true"> data-check-on-init="true">
<thead> <thead>
<tr class="d-flex"> <tr class="d-flex">
@ -128,10 +141,10 @@
<table class="table table-sm" <table class="table table-sm"
id="modulesTable" id="modulesTable"
data-auto-refresh="true" data-auto-refresh="true"
data-auto-refresh-interval="10" data-auto-refresh-interval="<?php echo GetCFGValue('dash_refresh'); ?>"
data-pagination="false" data-pagination="false"
data-card-view="true" data-card-view="true"
data-url="dashboardV2/jsonData/modules.php"> data-url="bin/getJson.php?jsonFile=modules">
<thead> <thead>
<tr class="d-flex"> <tr class="d-flex">
<th data-field="module" data-sortable="false">Module</th> <th data-field="module" data-sortable="false">Module</th>
@ -226,9 +239,9 @@
<table class="table table-sm" <table class="table table-sm"
id="procTable" id="procTable"
data-auto-refresh="true" data-auto-refresh="true"
data-auto-refresh-interval="15" data-auto-refresh-interval="<?php echo GetCFGValue('dash_refresh'); ?>"
data-pagination="false" data-pagination="false"
data-url="dashboardV2/jsonData/proc.php"> data-url="bin/getJson.php?jsonFile=ps">
<thead> <thead>
<tr class="d-flex"> <tr class="d-flex">
<th scope="col" data-field="user" data-sortable="false" class="d-none d-sm-table-cell">User</th> <th scope="col" data-field="user" data-sortable="false" class="d-none d-sm-table-cell">User</th>
@ -247,8 +260,8 @@
</div> <!-- End of Container --> </div> <!-- End of Container -->
<!-- Bootstrap table Javascript --> <!-- Bootstrap table Javascript -->
<script src="dashboardV2/js/bootstrap-table.min.js"></script> <script src="js/bootstrap-table.min.js"></script>
<script src="dashboardV2/js/bootstrap-table-auto-refresh.min.js"></script> <script src="js/bootstrap-table-auto-refresh.min.js"></script>
<!-- Enable Bootstrap tables and jQuery AJAX for QnRemote Control --> <!-- Enable Bootstrap tables and jQuery AJAX for QnRemote Control -->
<script> <script>
@ -263,7 +276,7 @@
var dataString = 'mod='+ processMod + '&URCall=' + processURCall; var dataString = 'mod='+ processMod + '&URCall=' + processURCall;
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: "dashboardV2/bin/qnRemoteCmd.php", url: "bin/qnRemoteCmd.php",
data: dataString, data: dataString,
success: function( returnData ) { success: function( returnData ) {
$('#last_cmd_sent').html("<div class=\"pb-2\" id=\"message\"></div>"); $('#last_cmd_sent').html("<div class=\"pb-2\" id=\"message\"></div>");

@ -1,31 +0,0 @@
<?php
header('Content-Type: application/json');
# Load functions and read config file
include '../init.php';
# Only proccess if defined in show list
if( in_array("LH", $showlist) ) {
$jsonArray = [];
$dbname = $cfgdir.'/qn.db';
$db = new SQLite3($dbname, SQLITE3_OPEN_READONLY);
$ss = 'SELECT callsign,sfx,message,module,reflector,maidenhead,latitude,longitude,strftime("%s","now")-lasttime as lastTime FROM LHEARD ORDER BY lastTime LIMIT '.GetCFGValue('dash_lastheard_count').' ';
if ($stmnt = $db->prepare($ss)) {
if ($result = $stmnt->execute()) {
while ($row = $result->FetchArray(SQLITE3_ASSOC)) {
//transform the lastTimeHeard to a printable string
$row['lastTime'] = SecToString($row['lastTime']);
$row['maidenheadProcessed'] = Maidenhead($row['maidenhead'], $row['latitude'], $row['longitude']);
$row['callsignProcessed'] = MyAndSfxToQrz($row['callsign'], $row['sfx']);
$jsonArray[] = $row;
}
$result->finalize();
}
$stmnt->close();
}
$db->Close();
echo json_encode($jsonArray);
} else { echo "Section disabled"; }
?>

@ -1,56 +0,0 @@
<?php
header('Content-Type: application/json');
#Load functions and read config file
include '../init.php';
# Only proccess if defined in show list
if( in_array("MO", $showlist) ) {
$jsonArray = [];
$dbname = $cfgdir.'/qn.db';
$db = new SQLite3($dbname, SQLITE3_OPEN_READONLY);
foreach (array('a', 'b', 'c') as $mod) {
$linkstatus = 'Unlinked';
$address = '';
$ctime = '';
$module = 'module_'.$mod;
if (array_key_exists($module, $cfg)) {
$freq = 0.0;
if (array_key_exists($module.'_tx_frequency', $cfg)) {
$freq = $cfg[$module.'_tx_frequency'];
}
else if (array_key_exists($module.'_frequency', $cfg)) {
$freq = $cfg[$module.'_frequency'];
}
$ss = 'SELECT ip_address,to_callsign,to_mod,strftime("%s","now")-linked_time as linkedTime FROM LINKSTATUS WHERE from_mod=' . "'" . strtoupper($mod) . "';";
if ($stmnt = $db->prepare($ss)) {
if ($result = $stmnt->execute()) {
if ($row = $result->FetchArray(SQLITE3_ASSOC)) {
$row['linkedTime'] = SecToString(intval($row['linkedTime']));
$row['module'] = strtoupper($mod);
$row['modem'] = $cfg[$module];
$row['freq'] = $freq;
$row['link'] = $row['to_callsign']." ".$row['to_mod'];
$jsonArray[] = $row;
} else {
$jsonArray[] = array('linkedTime' => '',
'module' =>strtoupper($mod),
'modem' => $cfg[$module],
'freq' => $freq,
'link' => 'Unlinked',
'ip_address' => '',
'to_callsign' => '',
'to_mod' => '');
}
$result->finalize();
}
$stmnt->close();
}
}
}
$db->close();
echo json_encode($jsonArray);
} else { echo "Section disabled"; }
?>

@ -1,24 +0,0 @@
<?php
header('Content-Type: application/json');
# Load functions and read config file
include '../init.php';
# Only proccess if defined in show list
if( in_array("PS", $showlist) ) {
$lines = explode("\n", `ps -eo user,pid,pcpu,size,cmd | grep -e qngateway -e qnlink -e qndtmf -e qndvap -e qnitap -e qnrelay -e qndvrptr -e qnmodem -e MMDVMHost | grep -v grep`);
foreach ($lines as $line) {
$items = preg_split ('/\s+/', $line, 5);
if( isset( $items[1] ) ) {
$jsonArray[] = array('user' => $items[0],
'pid' => $items[1],
'pcpu' => $items[2],
'size' => $items[3],
'cmd' => $items[4]);
}
}
if ($jsonArray) {
echo json_encode($jsonArray);
} else { echo '{ }'; }
} else { echo "Section disabled"; }
?>
Loading…
Cancel
Save

Powered by TurnKey Linux.