From 5da76e80a9fb64bfbda5897aa08fa1bc575dbd25 Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Fri, 13 Jan 2017 13:22:27 +0100 Subject: [statistics_reporting] improved cutoff in query functions + bugfix --- modules-available/statistics_reporting/hooks/cron.inc.php | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 modules-available/statistics_reporting/hooks/cron.inc.php (limited to 'modules-available/statistics_reporting/hooks/cron.inc.php') diff --git a/modules-available/statistics_reporting/hooks/cron.inc.php b/modules-available/statistics_reporting/hooks/cron.inc.php new file mode 100644 index 00000000..b79883df --- /dev/null +++ b/modules-available/statistics_reporting/hooks/cron.inc.php @@ -0,0 +1,3 @@ + array(), 'perClient' => array(), 'perUser' => array(), 'perVM' => array())); + $data['perLocation'] = GetData::perLocation(true); + $data['perClient'] = GetData::perClient(true); + $data['perUser'] = GetData::perUser(true); + $data['perVM'] = GetData::perVM(); + + + $statisticsReport = json_encode($data); + + $url = CONFIG_REPORTING_URL; + + $curl = curl_init($url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json")); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $statisticsReport); + + $json_response = curl_exec($curl); + + curl_close($curl); +} -- cgit v1.2.3-55-g7522 From 4910fa0b9f5ca6b6063965cc516ced8d72f8be5b Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Tue, 17 Jan 2017 13:47:24 +0100 Subject: [statistics_reporting] added vm name anonymization --- modules-available/statistics_reporting/hooks/cron.inc.php | 2 +- modules-available/statistics_reporting/inc/getdata.inc.php | 5 +++-- modules-available/statistics_reporting/inc/queries.inc.php | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'modules-available/statistics_reporting/hooks/cron.inc.php') diff --git a/modules-available/statistics_reporting/hooks/cron.inc.php b/modules-available/statistics_reporting/hooks/cron.inc.php index 57e64a84..9b32bc96 100644 --- a/modules-available/statistics_reporting/hooks/cron.inc.php +++ b/modules-available/statistics_reporting/hooks/cron.inc.php @@ -16,7 +16,7 @@ if ($nextReporting < $time && $allowReport) { $data['perLocation'] = GetData::perLocation(true); $data['perClient'] = GetData::perClient(true); $data['perUser'] = GetData::perUser(true); - $data['perVM'] = GetData::perVM(); + $data['perVM'] = GetData::perVM(true); $statisticsReport = json_encode($data); diff --git a/modules-available/statistics_reporting/inc/getdata.inc.php b/modules-available/statistics_reporting/inc/getdata.inc.php index 880256d6..cfb63658 100644 --- a/modules-available/statistics_reporting/inc/getdata.inc.php +++ b/modules-available/statistics_reporting/inc/getdata.inc.php @@ -84,11 +84,12 @@ class GetData // per vm - public static function perVM() { + public static function perVM($anonymize = false) { $res = Queries::getVMStatistics(self::$from, self::$to, self::$lowerTimeBound, self::$upperTimeBound); $data = array(); + $vm = $anonymize ? 'vmHash' : 'name'; while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $data[] = array('vm' => $row['name'], 'sessions' => $row['count']); + $data[] = array('vm' => $row[$vm], 'sessions' => $row['count']); } return $data; } diff --git a/modules-available/statistics_reporting/inc/queries.inc.php b/modules-available/statistics_reporting/inc/queries.inc.php index 23f5fb03..219640a6 100644 --- a/modules-available/statistics_reporting/inc/queries.inc.php +++ b/modules-available/statistics_reporting/inc/queries.inc.php @@ -64,7 +64,7 @@ class Queries // Virtual Machine Data: Name, Number of Usages public static function getVMStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24) { - $res = Database::simpleQuery("SELECT data AS name, COUNT(*) AS 'count' + $res = Database::simpleQuery("SELECT data AS name, MD5(data) AS vmHash, COUNT(*) AS 'count' FROM statistic WHERE typeid='.vmchooser-session-name' AND dateline+data >= $from and dateline <= $to AND ( (@daysDiff := (TO_DAYS(FROM_UNIXTIME(@end := IF(dateline+data > $to, $to, dateline+data), '%y-%m-%d')) - TO_DAYS(FROM_UNIXTIME(@start := IF(dateline < $from, $from, dateline), '%y-%m-%d'))) = 0 -- cgit v1.2.3-55-g7522 From 6e9d2635c9fe69923a4c30cb99ab6938bfbffe27 Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Tue, 17 Jan 2017 14:24:41 +0100 Subject: [statistics_reporting] improved anonymization --- .../statistics_reporting/hooks/cron.inc.php | 19 ++++++++----------- .../statistics_reporting/inc/getdata.inc.php | 2 +- .../statistics_reporting/inc/queries.inc.php | 17 +++++++++-------- 3 files changed, 18 insertions(+), 20 deletions(-) (limited to 'modules-available/statistics_reporting/hooks/cron.inc.php') diff --git a/modules-available/statistics_reporting/hooks/cron.inc.php b/modules-available/statistics_reporting/hooks/cron.inc.php index 9b32bc96..bd427e64 100644 --- a/modules-available/statistics_reporting/hooks/cron.inc.php +++ b/modules-available/statistics_reporting/hooks/cron.inc.php @@ -9,8 +9,9 @@ if ($nextReporting < $time && $allowReport) { Property::set("nextReporting", strtotime("Sunday 23:59:59")); - GetData::$from = strtotime("Monday last week"); - GetData::$to = strtotime("Sunday last week 23:59:59"); + GetData::$from = strtotime("last sunday - 6 days"); + GetData::$to = strtotime("last sunday 23:59:59"); + GetData::$salt = bin2hex(random_bytes(20)); $data = array_merge(GetData::total(true), array('perLocation' => array(), 'perClient' => array(), 'perUser' => array(), 'perVM' => array())); $data['perLocation'] = GetData::perLocation(true); @@ -21,15 +22,11 @@ if ($nextReporting < $time && $allowReport) { $statisticsReport = json_encode($data); - $url = CONFIG_REPORTING_URL; + $params = array("action" => "statistics", "data" => $statisticsReport); - $curl = curl_init($url); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json")); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, $statisticsReport); + Download::asStringPost(CONFIG_REPORTING_URL, $params, 300, $code); - $json_response = curl_exec($curl); - - curl_close($curl); + if ($code != 200) { + EventLog::warning("Statistics Reporting: ".$code); + } } diff --git a/modules-available/statistics_reporting/inc/getdata.inc.php b/modules-available/statistics_reporting/inc/getdata.inc.php index cfb63658..07a13a0c 100644 --- a/modules-available/statistics_reporting/inc/getdata.inc.php +++ b/modules-available/statistics_reporting/inc/getdata.inc.php @@ -6,7 +6,7 @@ class GetData public static $to; public static $lowerTimeBound = 0; public static $upperTimeBound = 24; - + public static $salt; // total public static function total($anonymize = false) { diff --git a/modules-available/statistics_reporting/inc/queries.inc.php b/modules-available/statistics_reporting/inc/queries.inc.php index 219640a6..77deb4f8 100644 --- a/modules-available/statistics_reporting/inc/queries.inc.php +++ b/modules-available/statistics_reporting/inc/queries.inc.php @@ -7,7 +7,7 @@ class Queries // Client Data: Name, Time Online, Median Time Online, Time Offline, last start, last logout, Last Time Booted, Number of Sessions > 60Sec, Number of Sessions < 60Sec, name of location, id of location (anonymized), machine uuid (anonymized) public static function getClientStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24, $excludeToday = false) { $notassigned = Dictionary::translateFile('template-tags', 'lang_notassigned'); - $res = Database::simpleQuery("SELECT t1.name AS clientName, timeSum, medianTime, offlineSum, lastStart, lastLogout, longSessions, shortSessions, locName, MD5(locId) AS locHash, MD5(t1.uuid) AS clientHash FROM ( + $res = Database::simpleQuery("SELECT t1.name AS clientName, timeSum, medianTime, offlineSum, lastStart, lastLogout, longSessions, shortSessions, locName, MD5(CONCAT(locId, :salt)) AS locHash, MD5(CONCAT(t1.uuid, :salt)) AS clientHash FROM ( SELECT machine.hostname AS 'name', machine.machineuuid AS 'uuid', SUM(CAST(sessionTable.length AS UNSIGNED)) AS 'timeSum', GROUP_CONCAT(sessionTable.length) AS 'medianTime', SUM(sessionTable.length >= 60) AS 'longSessions', SUM(sessionTable.length < 60) AS 'shortSessions',MAX(sessionTable.dateline + sessionTable.data) AS 'lastLogout', IFNULL(location.locationname, '$notassigned') AS 'locName', location.locationid AS 'locId' FROM ".self::getBoundedTableQueryString('~session-length', $from, $to, $lowerTimeBound, $upperTimeBound)." sessionTable INNER JOIN machine ON sessionTable.machineuuid = machine.machineuuid @@ -20,14 +20,15 @@ class Queries INNER JOIN machine ON offlineTable.machineuuid = machine.machineuuid GROUP BY machine.machineuuid ) t2 - ON t1.uuid = t2.uuid"); + ON t1.uuid = t2.uuid", array("salt" => GetData::$salt)); + return $res; } // Location Data: Name, ID (anonymized), Time Online, Median Time Online, Time Offline, Number of Sessions > 60Sec, Number of Sessions < 60Sec public static function getLocationStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24, $excludeToday = false) { $notassigned = Dictionary::translateFile('template-tags', 'lang_notassigned'); - $res = Database::simpleQuery("SELECT t1.locName AS locName, MD5(locId) AS locHash, timeSum, medianTime, offlineSum, longSessions, shortSessions FROM ( + $res = Database::simpleQuery("SELECT t1.locName AS locName, MD5(CONCAT(locId, :salt)) AS locHash, timeSum, medianTime, offlineSum, longSessions, shortSessions FROM ( SELECT IFNULL(location.locationname, '$notassigned') AS 'locName', location.locationid AS 'locId', SUM(CAST(sessionTable.length AS UNSIGNED)) AS 'timeSum', GROUP_CONCAT(sessionTable.length) AS 'medianTime', SUM(sessionTable.length >= 60) AS 'longSessions', SUM(sessionTable.length < 60) AS 'shortSessions' FROM ".self::getBoundedTableQueryString('~session-length', $from, $to, $lowerTimeBound, $upperTimeBound)." sessionTable INNER JOIN machine ON sessionTable.machineuuid = machine.machineuuid @@ -41,13 +42,13 @@ class Queries LEFT JOIN location ON machine.locationid = location.locationid GROUP BY location.locationname ) t2 - ON t1.locName = t2.locName"); + ON t1.locName = t2.locName", array("salt" => GetData::$salt)); return $res; } // User Data: Name, Name(anonymized), Number of Logins public static function getUserStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24) { - $res = Database::simpleQuery("SELECT username AS name, IF(username = 'anonymous', 'anonymous', md5(username)) AS userHash, COUNT(*) AS 'count' + $res = Database::simpleQuery("SELECT username AS name, IF(username = 'anonymous', 'anonymous', md5(CONCAT(username, :salt))) AS userHash, COUNT(*) AS 'count' FROM statistic WHERE typeid='.vmchooser-session-name' AND dateline+data >= $from and dateline <= $to AND ( (@daysDiff := (TO_DAYS(FROM_UNIXTIME(@end := IF(dateline+data > $to, $to, dateline+data), '%y-%m-%d')) - TO_DAYS(FROM_UNIXTIME(@start := IF(dateline < $from, $from, dateline), '%y-%m-%d'))) = 0 @@ -58,13 +59,13 @@ class Queries @daysDiff >= 2 ) GROUP BY username - ORDER BY 2 DESC"); + ORDER BY 2 DESC", array("salt" => GetData::$salt)); return $res; } // Virtual Machine Data: Name, Number of Usages public static function getVMStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24) { - $res = Database::simpleQuery("SELECT data AS name, MD5(data) AS vmHash, COUNT(*) AS 'count' + $res = Database::simpleQuery("SELECT data AS name, MD5(CONCAT(data, :salt)) AS vmHash, COUNT(*) AS 'count' FROM statistic WHERE typeid='.vmchooser-session-name' AND dateline+data >= $from and dateline <= $to AND ( (@daysDiff := (TO_DAYS(FROM_UNIXTIME(@end := IF(dateline+data > $to, $to, dateline+data), '%y-%m-%d')) - TO_DAYS(FROM_UNIXTIME(@start := IF(dateline < $from, $from, dateline), '%y-%m-%d'))) = 0 @@ -75,7 +76,7 @@ class Queries @daysDiff >= 2 ) GROUP BY data - ORDER BY 2 DESC"); + ORDER BY 2 DESC", array("salt" => GetData::$salt)); return $res; } -- cgit v1.2.3-55-g7522 From 886e13e1af47ba6488ba3c5146d96e48e08403ad Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 19 Jan 2017 16:03:06 +0100 Subject: [statistics_reporting] Overhaul remote reporting structure; default to off --- inc/util.inc.php | 52 ++++++++++++++ .../statistics_reporting/hooks/cron.inc.php | 37 ++++------ .../statistics_reporting/inc/remotereport.inc.php | 84 ++++++++++++++++++++++ .../statistics_reporting/page.inc.php | 22 +++--- .../templates/columnChooser.html | 4 +- 5 files changed, 166 insertions(+), 33 deletions(-) create mode 100644 modules-available/statistics_reporting/inc/remotereport.inc.php (limited to 'modules-available/statistics_reporting/hooks/cron.inc.php') diff --git a/inc/util.inc.php b/inc/util.inc.php index 671028ed..d454d18d 100644 --- a/inc/util.inc.php +++ b/inc/util.inc.php @@ -365,4 +365,56 @@ SADFACE; exit(0); } + /** + * Return a binary string of given length, containing + * random bytes. If $secure is given, only methods of + * obtaining cryptographically strong random bytes will + * be used, otherwise, weaker methods might be used. + * + * @param int $length number of bytes to return + * @param bool $secure true = only use strong random sources + * @return string|bool string of requested length, false on error + */ + public static function randomBytes($length, $secure) + { + if (function_exists('random_bytes')) { + return random_bytes($length); + } + if ($secure) { + if (function_exists('openssl_random_pseudo_bytes')) { + $bytes = openssl_random_pseudo_bytes($length, $ok); + if ($bytes !== false && $ok) { + return $bytes; + } + } + $file = '/dev/random'; + } else { + $file = '/dev/urandom'; + } + $fh = @fopen($file, 'r'); + if ($fh !== false) { + $bytes = fread($fh, $length); + while ($bytes !== false && strlen($bytes) < $length) { + $new = fread($fh, $length - strlen($bytes)); + if ($new === false) { + $bytes = false; + break; + } + $bytes .= $new; + } + fclose($fh); + if ($bytes !== false) { + return $bytes; + } + } + if ($secure) { + return false; + } + $bytes = ''; + while ($length > 0) { + $bytes .= chr(mt_rand(0, 255)); + } + return $bytes; + } + } diff --git a/modules-available/statistics_reporting/hooks/cron.inc.php b/modules-available/statistics_reporting/hooks/cron.inc.php index bd427e64..a48f74c2 100644 --- a/modules-available/statistics_reporting/hooks/cron.inc.php +++ b/modules-available/statistics_reporting/hooks/cron.inc.php @@ -1,32 +1,23 @@ "statistics", "data" => $statisticsReport); - $data = array_merge(GetData::total(true), array('perLocation' => array(), 'perClient' => array(), 'perUser' => array(), 'perVM' => array())); - $data['perLocation'] = GetData::perLocation(true); - $data['perClient'] = GetData::perClient(true); - $data['perUser'] = GetData::perUser(true); - $data['perVM'] = GetData::perVM(true); + $result = Download::asStringPost(CONFIG_REPORTING_URL, $params, 30, $code); - - $statisticsReport = json_encode($data); - - $params = array("action" => "statistics", "data" => $statisticsReport); - - Download::asStringPost(CONFIG_REPORTING_URL, $params, 300, $code); - - if ($code != 200) { - EventLog::warning("Statistics Reporting: ".$code); + if ($code != 200) { + EventLog::warning("Statistics Reporting failed: " . $code, $result); + } } -} +} \ No newline at end of file diff --git a/modules-available/statistics_reporting/inc/remotereport.inc.php b/modules-available/statistics_reporting/inc/remotereport.inc.php new file mode 100644 index 00000000..0bf4e7e2 --- /dev/null +++ b/modules-available/statistics_reporting/inc/remotereport.inc.php @@ -0,0 +1,84 @@ +action = Request::any('action', false, 'string'); - if ($this->action === 'setReporting') { - Property::set("reportingStatus", Request::get('reporting', "on", 'string')); - } elseif ($this->action === 'getReporting') { - echo Property::get("reportingStatus", "on"); + $this->action = Request::any('action', false, 'string'); + if ($this->action === 'setReporting') { + if (!User::isLoggedIn()) { + die("No."); + } + $state = Request::post('reporting', false, 'string'); + if ($state === false) { + die('Missing setting value.'); } + RemoteReport::setReportingEnabled($state); + } elseif ($this->action === 'getReporting') { + echo RemoteReport::isReportingEnabled() ? 'on' : ''; + } else { + echo 'Invalid action.'; } } + } diff --git a/modules-available/statistics_reporting/templates/columnChooser.html b/modules-available/statistics_reporting/templates/columnChooser.html index 47fef2a5..513bc36b 100644 --- a/modules-available/statistics_reporting/templates/columnChooser.html +++ b/modules-available/statistics_reporting/templates/columnChooser.html @@ -189,8 +189,8 @@ function saveSettings() { $.ajax({ url: '?do=statistics_reporting', - type: 'GET', - data: { action: "setReporting", reporting: $("#checkbox-reporting").is(":checked") ? "on" : "off" } + type: 'POST', + data: { action: "setReporting", reporting: $("#checkbox-reporting").is(":checked") ? "on" : "off", token: TOKEN } }); } \ No newline at end of file -- cgit v1.2.3-55-g7522