From 4c4b2a6df3832d61bcc26001c49b654624e3ad97 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Wed, 19 Dec 2018 14:12:42 +0100 Subject: [PATCH] use TwoFactorAuth via composer Signed-off-by: Michael Kaufmann --- api.php | 2 +- composer.json | 3 +- .../Bulk/BulkAction.php} | 46 +-- .../Bulk/DomainBulkAction.php} | 25 +- .../Database/IntegrityCheck.php} | 347 ++++++++++-------- lib/Froxlor/FroxlorTwoFactorAuth.php | 21 ++ lib/classes/2FA/.gitignore | 189 ---------- .../2FA/class.FroxlorTwoFactorAuth.php | 38 -- .../Providers/Qr/BaseHTTPQRCodeProvider.php | 27 -- .../lib/Providers/Qr/GoogleQRCodeProvider.php | 39 -- .../2FA/lib/Providers/Qr/IQRCodeProvider.php | 9 - .../2FA/lib/Providers/Qr/QRException.php | 5 - .../2FA/lib/Providers/Qr/QRServerProvider.php | 71 ---- .../2FA/lib/Providers/Qr/QRicketProvider.php | 54 --- .../2FA/lib/Providers/Rng/CSRNGProvider.php | 14 - .../2FA/lib/Providers/Rng/HashRNGProvider.php | 28 -- .../2FA/lib/Providers/Rng/IRNGProvider.php | 9 - .../lib/Providers/Rng/MCryptRNGProvider.php | 23 -- .../lib/Providers/Rng/OpenSSLRNGProvider.php | 25 -- .../2FA/lib/Providers/Rng/RNGException.php | 5 - .../lib/Providers/Time/HttpTimeProvider.php | 54 --- .../2FA/lib/Providers/Time/ITimeProvider.php | 8 - .../Time/LocalMachineTimeProvider.php | 9 - .../lib/Providers/Time/NTPTimeProvider.php | 52 --- .../2FA/lib/Providers/Time/TimeException.php | 5 - lib/classes/2FA/lib/TwoFactorAuth.php | 256 ------------- .../2FA/lib/TwoFactorAuthException.php | 7 - lib/functions.php | 6 - .../filedir/function.createCustomerBackup.php | 17 - 29 files changed, 264 insertions(+), 1130 deletions(-) rename lib/{classes/bulk/abstract.BulkAction.php => Froxlor/Bulk/BulkAction.php} (78%) rename lib/{classes/bulk/class.DomainBulkAction.php => Froxlor/Bulk/DomainBulkAction.php} (82%) rename lib/{classes/integrity/class.IntegrityCheck.php => Froxlor/Database/IntegrityCheck.php} (61%) create mode 100644 lib/Froxlor/FroxlorTwoFactorAuth.php delete mode 100644 lib/classes/2FA/.gitignore delete mode 100644 lib/classes/2FA/class.FroxlorTwoFactorAuth.php delete mode 100644 lib/classes/2FA/lib/Providers/Qr/BaseHTTPQRCodeProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Qr/GoogleQRCodeProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Qr/IQRCodeProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Qr/QRException.php delete mode 100644 lib/classes/2FA/lib/Providers/Qr/QRServerProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Qr/QRicketProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Rng/CSRNGProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Rng/HashRNGProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Rng/IRNGProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Rng/MCryptRNGProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Rng/OpenSSLRNGProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Rng/RNGException.php delete mode 100644 lib/classes/2FA/lib/Providers/Time/HttpTimeProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Time/ITimeProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Time/LocalMachineTimeProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Time/NTPTimeProvider.php delete mode 100644 lib/classes/2FA/lib/Providers/Time/TimeException.php delete mode 100644 lib/classes/2FA/lib/TwoFactorAuth.php delete mode 100644 lib/classes/2FA/lib/TwoFactorAuthException.php delete mode 100644 lib/functions/filedir/function.createCustomerBackup.php diff --git a/api.php b/api.php index ab7f4ddf..f27b1f0e 100644 --- a/api.php +++ b/api.php @@ -32,7 +32,7 @@ if (is_null($decoded_request)) { try { $request = \Froxlor\Api\FroxlorRPC::validateRequest($decoded_request); // now actually do it - $cls = "\Froxlor\Api\Commands\\" . $request['command']['class']; + $cls = "\\Froxlor\\Api\\Commands\\" . $request['command']['class']; $method = $request['command']['method']; $apiObj = new $cls($decoded_request['header'], $request['params']); // call the method with the params if any diff --git a/composer.json b/composer.json index 1ca89aae..9093a729 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,8 @@ "ext-openssl": "*", "mso/idna-convert" : "1.*", "phpmailer/phpmailer": "~6.0", - "monolog/monolog": "^1.24" + "monolog/monolog": "^1.24", + "robthree/twofactorauth": "^1.6" }, "require-dev" : { "phpunit/phpunit" : "6.5.13", diff --git a/lib/classes/bulk/abstract.BulkAction.php b/lib/Froxlor/Bulk/BulkAction.php similarity index 78% rename from lib/classes/bulk/abstract.BulkAction.php rename to lib/Froxlor/Bulk/BulkAction.php index 336c6758..25826f11 100644 --- a/lib/classes/bulk/abstract.BulkAction.php +++ b/lib/Froxlor/Bulk/BulkAction.php @@ -1,4 +1,5 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Cron - * - * @since 0.10.0 - * + * @copyright (c) the authors + * @author Michael Kaufmann + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron + * + * @since 0.10.0 + * */ /** @@ -80,7 +81,7 @@ abstract class BulkAction protected function __construct($import_file = null, $customer_id = 0) { if (! empty($import_file)) { - $this->_impFile = makeCorrectFile($import_file); + $this->_impFile = \Froxlor\FileDir::makeCorrectFile($import_file); } $this->_custId = $customer_id; } @@ -105,7 +106,7 @@ abstract class BulkAction */ public function setImportFile($import_file = null) { - $this->_impFile = makeCorrectFile($import_file); + $this->_impFile = \Froxlor\FileDir::makeCorrectFile($import_file); } /** @@ -146,13 +147,12 @@ abstract class BulkAction { global $userinfo; - $module = substr($this->api_call, 0, strpos($this->api_call, ".")); + $module = '\\Froxlor\\Api\\Commands\\' . substr($this->api_call, 0, strpos($this->api_call, ".")); $function = substr($this->api_call, strpos($this->api_call, ".") + 1); $new_data = array(); foreach ($this->api_params as $idx => $param) { - if (isset($data_array[$idx]) && !empty($data_array[$idx])) - { + if (isset($data_array[$idx]) && ! empty($data_array[$idx])) { $new_data[$param] = $data_array[$idx]; } } @@ -161,10 +161,10 @@ abstract class BulkAction try { $json_result = $module::getLocal($userinfo, $new_data)->$function(); $result = json_decode($json_result, true)['data']; - } catch (Exception $e) { + } catch (\Exception $e) { $this->errors[] = $e->getMessage(); } - return !empty($result); + return ! empty($result); } /** @@ -178,15 +178,15 @@ abstract class BulkAction protected function _parseImportFile($separator = ";") { if (empty($this->_impFile)) { - throw new Exception("No file was given for import"); + throw new \Exception("No file was given for import"); } if (! file_exists($this->_impFile)) { - throw new Exception("The file '" . $this->_impFile . "' could not be found"); + throw new \Exception("The file '" . $this->_impFile . "' could not be found"); } if (! is_readable($this->_impFile)) { - throw new Exception("Unable to read file '" . $this->_impFile . "'"); + throw new \Exception("Unable to read file '" . $this->_impFile . "'"); } $file_data = array(); @@ -211,7 +211,7 @@ abstract class BulkAction } $this->api_params = array_map("trim", $this->api_params); } else { - throw new Exception("Unable to open file '" . $this->_impFile . "'"); + throw new \Exception("Unable to open file '" . $this->_impFile . "'"); } fclose($fh); @@ -226,11 +226,11 @@ abstract class BulkAction $this->_readCustomerData(); if ($this->_custId <= 0) { - throw new Exception("Invalid customer selected"); + throw new \Exception("Invalid customer selected"); } if (is_null($this->_custData)) { - throw new Exception("Failed to read customer data"); + throw new \Exception("Failed to read customer data"); } } @@ -241,8 +241,8 @@ abstract class BulkAction */ protected function _readCustomerData() { - $cust_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :cid"); - $this->_custData = Database::pexecute_first($cust_stmt, array( + $cust_stmt = \Froxlor\Database\Database::prepare("SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :cid"); + $this->_custData = \Froxlor\Database\Database::pexecute_first($cust_stmt, array( 'cid' => $this->_custId )); if (is_array($this->_custData) && isset($this->_custData['customerid']) && $this->_custData['customerid'] == $this->_custId) { diff --git a/lib/classes/bulk/class.DomainBulkAction.php b/lib/Froxlor/Bulk/DomainBulkAction.php similarity index 82% rename from lib/classes/bulk/class.DomainBulkAction.php rename to lib/Froxlor/Bulk/DomainBulkAction.php index 47a9f7c1..b0126265 100644 --- a/lib/classes/bulk/class.DomainBulkAction.php +++ b/lib/Froxlor/Bulk/DomainBulkAction.php @@ -1,4 +1,5 @@ - * @author Froxlor team (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Cron - * - * @since 0.9.33 - * + * @copyright (c) the authors + * @author Michael Kaufmann + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron + * + * @since 0.9.33 + * */ /** @@ -63,21 +64,21 @@ class DomainBulkAction extends BulkAction $domains_avail = (int) $userinfo['domains']; if (empty($separator) || strlen($separator) != 1) { - throw new Exception("Invalid separator specified: '" . $separator . "'"); + throw new \Exception("Invalid separator specified: '" . $separator . "'"); } if (! is_int($offset) || $offset < 0) { - throw new Exception("Invalid offset specified"); + throw new \Exception("Invalid offset specified"); } try { $domain_array = $this->_parseImportFile($separator); - } catch (Exception $e) { + } catch (\Exception $e) { throw $e; } if (count($domain_array) <= 0) { - throw new Exception("No domains were read from the file."); + throw new \Exception("No domains were read from the file."); } $global_counter = 0; diff --git a/lib/classes/integrity/class.IntegrityCheck.php b/lib/Froxlor/Database/IntegrityCheck.php similarity index 61% rename from lib/classes/integrity/class.IntegrityCheck.php rename to lib/Froxlor/Database/IntegrityCheck.php index bc0a7dad..050e5f9a 100644 --- a/lib/classes/integrity/class.IntegrityCheck.php +++ b/lib/Froxlor/Database/IntegrityCheck.php @@ -1,4 +1,7 @@ - * @author Froxlor team (2014-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Integrity - * - * IntegrityCheck - class + * @copyright (c) the authors + * @author Florian Aders + * @author Froxlor team (2014-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Integrity + * + * IntegrityCheck - class */ - -class IntegrityCheck { +class IntegrityCheck +{ // Store all available checks public $available = array(); @@ -30,24 +33,27 @@ class IntegrityCheck { * Constructor * Parses all available checks into $this->available */ - public function __construct() { + public function __construct() + { global $userinfo; - if (!isset($userinfo) || !is_array($userinfo)) { - $userinfo = array('loginname' => 'integrity-check'); + if (! isset($userinfo) || ! is_array($userinfo)) { + $userinfo = array( + 'loginname' => 'integrity-check' + ); } - $this->_log = FroxlorLogger::getInstanceOf($userinfo); + $this->_log = \Froxlor\FroxlorLogger::getInstanceOf($userinfo); $this->available = get_class_methods($this); unset($this->available[array_search('__construct', $this->available)]); unset($this->available[array_search('checkAll', $this->available)]); unset($this->available[array_search('fixAll', $this->available)]); sort($this->available); - } /** * Check all occurring integrity problems at once */ - public function checkAll() { + public function checkAll() + { $integrityok = true; foreach ($this->available as $check) { $integrityok = $this->$check() ? $integrityok : false; @@ -58,7 +64,8 @@ class IntegrityCheck { /** * Fix all occurring integrity problems at once with default settings */ - public function fixAll() { + public function fixAll() + { $integrityok = true; foreach ($this->available as $check) { $integrityok = $this->$check(true) ? $integrityok : false; @@ -69,24 +76,28 @@ class IntegrityCheck { /** * check whether the froxlor database and its tables are in utf-8 character-set * - * @param bool $fix fix db charset/collation if not utf8 - * + * @param bool $fix + * fix db charset/collation if not utf8 + * * @return boolean */ - public function DatabaseCharset($fix = false) { + public function DatabaseCharset($fix = false) + { // get characterset $cs_stmt = Database::prepare('SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = :dbname'); - $resp = Database::pexecute_first($cs_stmt, array('dbname' => Database::getDbName())); + $resp = Database::pexecute_first($cs_stmt, array( + 'dbname' => Database::getDbName() + )); $charset = isset($resp['default_character_set_name']) ? $resp['default_character_set_name'] : null; - if (!empty($charset) && strtolower($charset) != 'utf8') { + if (! empty($charset) && strtolower($charset) != 'utf8') { $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "database charset seems to be different from UTF-8, integrity-check can fix that"); if ($fix) { // fix database Database::query('ALTER DATABASE `' . Database::getDbName() . '` CHARACTER SET utf8 COLLATE utf8_general_ci'); // fix all tables $handle = Database::query('SHOW FULL TABLES WHERE Table_type != "VIEW"'); - while ($row = $handle->fetch(PDO::FETCH_BOTH)) { + while ($row = $handle->fetch(\PDO::FETCH_BOTH)) { $table = $row[0]; Database::query('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;'); } @@ -104,9 +115,12 @@ class IntegrityCheck { /** * Check the integrity of the domain to ip/port - association - * @param $fix Fix everything found directly + * + * @param bool $fix + * Fix everything found directly */ - public function DomainIpTable($fix = false) { + public function DomainIpTable($fix = false) + { $ips = array(); $domains = array(); $ipstodomains = array(); @@ -116,24 +130,24 @@ class IntegrityCheck { // Prepare insert / delete statement for the fixes $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_DOMAINTOIP . "` - WHERE `id_domain` = :domainid AND `id_ipandports` = :ipandportid " - ); + WHERE `id_domain` = :domainid AND `id_ipandports` = :ipandportid "); $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_DOMAINTOIP . "` - SET `id_domain` = :domainid, `id_ipandports` = :ipandportid " - ); + SET `id_domain` = :domainid, `id_ipandports` = :ipandportid "); // Cache all IPs the admins have assigned $adm_stmt = Database::prepare("SELECT `adminid`, `ip` FROM `" . TABLE_PANEL_ADMINS . "` ORDER BY `adminid` ASC"); Database::pexecute($adm_stmt); $default_ips = explode(',', Settings::Get('system.defaultip')); $default_ssl_ips = explode(',', Settings::Get('system.defaultsslip')); - while ($row = $adm_stmt->fetch(PDO::FETCH_ASSOC)) { + while ($row = $adm_stmt->fetch(\PDO::FETCH_ASSOC)) { if ($row['ip'] < 0 || is_null($row['ip']) || empty($row['ip'])) { // Admin uses default-IP $admips[$row['adminid']] = array_merge($default_ips, $default_ssl_ips); } else { - $admips[$row['adminid']] = array($row['ip']); + $admips[$row['adminid']] = array( + $row['ip'] + ); } } } @@ -141,33 +155,39 @@ class IntegrityCheck { // Cache all available ip/port - combinations $result_stmt = Database::prepare("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } // Cache all configured domains $result_stmt = Database::prepare("SELECT `id`, `adminid` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $domains[$row['id']] = $row['adminid']; } // Check if every domain to ip/port - association is valid in TABLE_DOMAINTOIP $result_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "`"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { - if (!array_key_exists($row['id_ipandports'], $ips)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { + if (! array_key_exists($row['id_ipandports'], $ips)) { if ($fix) { - Database::pexecute($del_stmt, array('domainid' => $row['id_domain'], 'ipandportid' => $row['id_ipandports'])); + Database::pexecute($del_stmt, array( + 'domainid' => $row['id_domain'], + 'ipandportid' => $row['id_ipandports'] + )); $this->_log->logAction(ADM_ACTION, LOG_WARNING, "found an ip/port-id in domain <> ip table which does not exist, integrity check fixed this"); } else { $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "found an ip/port-id in domain <> ip table which does not exist, integrity check can fix this"); return false; } } - if (!array_key_exists($row['id_domain'], $domains)) { + if (! array_key_exists($row['id_domain'], $domains)) { if ($fix) { - Database::pexecute($del_stmt, array('domainid' => $row['id_domain'], 'ipandportid' => $row['id_ipandports'])); + Database::pexecute($del_stmt, array( + 'domainid' => $row['id_domain'], + 'ipandportid' => $row['id_ipandports'] + )); $this->_log->logAction(ADM_ACTION, LOG_WARNING, "found a domain-id in domain <> ip table which does not exist, integrity check fixed this"); } else { $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "found a domain-id in domain <> ip table which does not exist, integrity check can fix this"); @@ -180,10 +200,13 @@ class IntegrityCheck { // Check that all domains have at least one IP/Port combination foreach ($domains as $domainid => $adminid) { - if (!array_key_exists($domainid, $ipstodomains)) { + if (! array_key_exists($domainid, $ipstodomains)) { if ($fix) { foreach ($admips[$adminid] as $defaultip) { - Database::pexecute($ins_stmt, array('domainid' => $domainid, 'ipandportid' => $defaultip)); + Database::pexecute($ins_stmt, array( + 'domainid' => $domainid, + 'ipandportid' => $defaultip + )); } $this->_log->logAction(ADM_ACTION, LOG_WARNING, "found a domain-id with no entry in domain <> ip table, integrity check fixed this"); } else { @@ -202,9 +225,12 @@ class IntegrityCheck { /** * Check if all subdomains have ssl-redirect = 0 if domain has no ssl-port - * @param $fix Fix everything found directly + * + * @param bool $fix + * Fix everything found directly */ - public function SubdomainSslRedirect($fix = false) { + public function SubdomainSslRedirect($fix = false) + { $ips = array(); $parentdomains = array(); $subdomains = array(); @@ -213,14 +239,13 @@ class IntegrityCheck { // Prepare update statement for the fixes $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` - SET `ssl_redirect` = 0 WHERE `parentdomainid` = :domainid" - ); + SET `ssl_redirect` = 0 WHERE `parentdomainid` = :domainid"); } // Cache all ssl ip/port - combinations $result_stmt = Database::prepare("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl` = 1 ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } @@ -228,18 +253,24 @@ class IntegrityCheck { $result_stmt = Database::prepare("SELECT `id`, `parentdomainid`, `ssl_redirect` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC"); $ip_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :domainid"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { if ($row['parentdomainid'] == 0) { // All parentdomains by default have no ssl - ip/port $parentdomains[$row['id']] = false; - Database::pexecute($ip_stmt, array('domainid' => $row['id'])); - while ($iprow = $ip_stmt->fetch(PDO::FETCH_ASSOC)) { + Database::pexecute($ip_stmt, array( + 'domainid' => $row['id'] + )); + while ($iprow = $ip_stmt->fetch(\PDO::FETCH_ASSOC)) { // If the parentdomain has an ip/port assigned which we know is SSL enabled, set the parentdomain to "true" - if (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; } + if (array_key_exists($iprow['id_ipandports'], $ips)) { + $parentdomains[$row['id']] = true; + } } - } elseif ($row['ssl_redirect'] == 1) { + } elseif ($row['ssl_redirect'] == 1) { // All subdomains with enabled ssl_redirect enabled are stored - if (!isset($subdomains[$row['parentdomainid']])) { $subdomains[$row['parentdomainid']] = array(); } + if (! isset($subdomains[$row['parentdomainid']])) { + $subdomains[$row['parentdomainid']] = array(); + } $subdomains[$row['parentdomainid']][] = $row['id']; } } @@ -247,14 +278,20 @@ class IntegrityCheck { // Check if every parentdomain with enabled ssl_redirect as SSL enabled foreach ($parentdomains as $id => $sslavailable) { // This parentdomain has no subdomains - if (!isset($subdomains[$id])) { continue; } + if (! isset($subdomains[$id])) { + continue; + } // This parentdomain has SSL enabled, doesn't matter what status the subdomains have - if ($sslavailable) { continue; } + if ($sslavailable) { + continue; + } // At this point only parentdomains reside which have ssl_redirect enabled subdomains if ($fix) { // We make a blanket update to all subdomains of this parentdomain, doesn't matter which one is wrong, all have to be disabled - Database::pexecute($upd_stmt, array('domainid' => $id)); + Database::pexecute($upd_stmt, array( + 'domainid' => $id + )); $this->_log->logAction(ADM_ACTION, LOG_WARNING, "found a subdomain with ssl_redirect=1 but parent-domain has ssl=0, integrity check fixed this"); } else { // It's just the check, let the function fail @@ -272,9 +309,12 @@ class IntegrityCheck { /** * Check if all subdomain have letsencrypt = 0 if domain has no ssl-port - * @param $fix Fix everything found directly + * + * @param bool $fix + * Fix everything found directly */ - public function SubdomainLetsencrypt($fix = false) { + public function SubdomainLetsencrypt($fix = false) + { $ips = array(); $parentdomains = array(); $subdomains = array(); @@ -283,14 +323,13 @@ class IntegrityCheck { // Prepare update statement for the fixes $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_DOMAINS . "` - SET `letsencrypt` = 0 WHERE `parentdomainid` = :domainid" - ); + SET `letsencrypt` = 0 WHERE `parentdomainid` = :domainid"); } // Cache all ssl ip/port - combinations $result_stmt = Database::prepare("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `ssl` = 1 ORDER BY `id` ASC"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $ips[$row['id']] = $row['ip'] . ':' . $row['port']; } @@ -298,18 +337,24 @@ class IntegrityCheck { $result_stmt = Database::prepare("SELECT `id`, `parentdomainid`, `letsencrypt` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC"); $ip_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "` WHERE `id_domain` = :domainid"); Database::pexecute($result_stmt); - while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { if ($row['parentdomainid'] == 0) { // All parentdomains by default have no ssl - ip/port $parentdomains[$row['id']] = false; - Database::pexecute($ip_stmt, array('domainid' => $row['id'])); - while ($iprow = $ip_stmt->fetch(PDO::FETCH_ASSOC)) { + Database::pexecute($ip_stmt, array( + 'domainid' => $row['id'] + )); + while ($iprow = $ip_stmt->fetch(\PDO::FETCH_ASSOC)) { // If the parentdomain has an ip/port assigned which we know is SSL enabled, set the parentdomain to "true" - if (array_key_exists($iprow['id_ipandports'], $ips)) { $parentdomains[$row['id']] = true; } + if (array_key_exists($iprow['id_ipandports'], $ips)) { + $parentdomains[$row['id']] = true; + } } - } elseif ($row['letsencrypt'] == 1) { + } elseif ($row['letsencrypt'] == 1) { // All subdomains with enabled letsencrypt enabled are stored - if (!isset($subdomains[$row['parentdomainid']])) { $subdomains[$row['parentdomainid']] = array(); } + if (! isset($subdomains[$row['parentdomainid']])) { + $subdomains[$row['parentdomainid']] = array(); + } $subdomains[$row['parentdomainid']][] = $row['id']; } } @@ -317,14 +362,20 @@ class IntegrityCheck { // Check if every parentdomain with enabled letsencrypt as SSL enabled foreach ($parentdomains as $id => $sslavailable) { // This parentdomain has no subdomains - if (!isset($subdomains[$id])) { continue; } + if (! isset($subdomains[$id])) { + continue; + } // This parentdomain has SSL enabled, doesn't matter what status the subdomains have - if ($sslavailable) { continue; } + if ($sslavailable) { + continue; + } // At this point only parentdomains reside which have letsencrypt enabled subdomains if ($fix) { // We make a blanket update to all subdomains of this parentdomain, doesn't matter which one is wrong, all have to be disabled - Database::pexecute($upd_stmt, array('domainid' => $id)); + Database::pexecute($upd_stmt, array( + 'domainid' => $id + )); $this->_log->logAction(ADM_ACTION, LOG_WARNING, "found a subdomain with letsencrypt=1 but parent-domain has ssl=0, integrity check fixed this"); } else { // It's just the check, let the function fail @@ -344,46 +395,51 @@ class IntegrityCheck { * check whether the webserveruser is in * the customers groups when fcgid / php-fpm is used * - * @param bool $fix fix member/groups - * + * @param bool $fix + * fix member/groups + * * @return boolean */ - public function WebserverGroupMemberForFcgidPhpFpm($fix = false) { + public function WebserverGroupMemberForFcgidPhpFpm($fix = false) + { + if (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0) { + return true; + } - if (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0) { - return true; - } - - // get all customers that don't have the webserver-user in their group - $cwg_stmt = Database::prepare(" - SELECT `id` FROM `".TABLE_FTP_GROUPS."` WHERE NOT FIND_IN_SET(:webserveruser, `members`) + // get all customers that don't have the webserver-user in their group + $cwg_stmt = Database::prepare(" + SELECT `id` FROM `" . TABLE_FTP_GROUPS . "` WHERE NOT FIND_IN_SET(:webserveruser, `members`) "); - Database::pexecute($cwg_stmt, array('webserveruser' => Settings::Get('system.httpuser'))); + Database::pexecute($cwg_stmt, array( + 'webserveruser' => Settings::Get('system.httpuser') + )); - if ($cwg_stmt->rowCount() > 0) { - $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers are missing the webserver-user as group-member, integrity-check can fix that"); - if ($fix) { - // prepare update statement - $upd_stmt = Database::prepare(" - UPDATE `".TABLE_FTP_GROUPS."` SET `members` = CONCAT(`members`, :additionaluser) + if ($cwg_stmt->rowCount() > 0) { + $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers are missing the webserver-user as group-member, integrity-check can fix that"); + if ($fix) { + // prepare update statement + $upd_stmt = Database::prepare(" + UPDATE `" . TABLE_FTP_GROUPS . "` SET `members` = CONCAT(`members`, :additionaluser) WHERE `id` = :id "); - $upd_data = array('additionaluser' => ",".Settings::Get('system.httpuser')); + $upd_data = array( + 'additionaluser' => "," . Settings::Get('system.httpuser') + ); - while ($cwg_row = $cwg_stmt->fetch()) { - $upd_data['id'] = $cwg_row['id']; - Database::pexecute($upd_stmt, $upd_data); - } - $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers were missing the webserver-user as group-member, integrity-check fixed that"); - } else { - return false; - } - } + while ($cwg_row = $cwg_stmt->fetch()) { + $upd_data['id'] = $cwg_row['id']; + Database::pexecute($upd_stmt, $upd_data); + } + $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers were missing the webserver-user as group-member, integrity-check fixed that"); + } else { + return false; + } + } - if ($fix) { - return $this->WebserverGroupMemberForFcgidPhpFpm(); - } - return true; + if ($fix) { + return $this->WebserverGroupMemberForFcgidPhpFpm(); + } + return true; } /** @@ -391,61 +447,66 @@ class IntegrityCheck { * the customers groups when fcgid / php-fpm and * fcgid/fpm in froxlor vhost is used * - * @param bool $fix fix member/groups - * + * @param bool $fix + * fix member/groups + * * @return boolean */ - public function FroxlorLocalGroupMemberForFcgidPhpFpm($fix = false) { + public function FroxlorLocalGroupMemberForFcgidPhpFpm($fix = false) + { + if (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0) { + return true; + } - if (Settings::Get('system.mod_fcgid') == 0 && Settings::Get('phpfpm.enabled') == 0) { - return true; - } + if (Settings::get('system.mod_fcgid') == 1) { + if (Settings::get('system.mod_fcgid_ownvhost') == 0) { + return true; + } else { + $localuser = Settings::Get('system.mod_fcgid_httpuser'); + } + } - if (Settings::get('system.mod_fcgid') == 1) { - if (Settings::get('system.mod_fcgid_ownvhost') == 0) { - return true; - } else { - $localuser = Settings::Get('system.mod_fcgid_httpuser'); - } - } + if (Settings::get('phpfpm.enabled') == 1) { + if (Settings::get('phpfpm.enabled_ownvhost') == 0) { + return true; + } else { + $localuser = Settings::Get('phpfpm.vhost_httpuser'); + } + } - if (Settings::get('phpfpm.enabled') == 1) { - if (Settings::get('phpfpm.enabled_ownvhost') == 0) { - return true; - } else { - $localuser = Settings::Get('phpfpm.vhost_httpuser'); - } - } - - // get all customers that don't have the webserver-user in their group - $cwg_stmt = Database::prepare(" - SELECT `id` FROM `".TABLE_FTP_GROUPS."` WHERE NOT FIND_IN_SET(:localuser, `members`) + // get all customers that don't have the webserver-user in their group + $cwg_stmt = Database::prepare(" + SELECT `id` FROM `" . TABLE_FTP_GROUPS . "` WHERE NOT FIND_IN_SET(:localuser, `members`) "); - Database::pexecute($cwg_stmt, array('localuser' => $localuser)); + Database::pexecute($cwg_stmt, array( + 'localuser' => $localuser + )); - if ($cwg_stmt->rowCount() > 0) { - $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers are missing the local froxlor-user as group-member, integrity-check can fix that"); - if ($fix) { - // prepare update statement - $upd_stmt = Database::prepare(" - UPDATE `".TABLE_FTP_GROUPS."` SET `members` = CONCAT(`members`, :additionaluser) + if ($cwg_stmt->rowCount() > 0) { + $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers are missing the local froxlor-user as group-member, integrity-check can fix that"); + if ($fix) { + // prepare update statement + $upd_stmt = Database::prepare(" + UPDATE `" . TABLE_FTP_GROUPS . "` SET `members` = CONCAT(`members`, :additionaluser) WHERE `id` = :id "); - $upd_data = array('additionaluser' => ",".$localuser); + $upd_data = array( + 'additionaluser' => "," . $localuser + ); - while ($cwg_row = $cwg_stmt->fetch()) { - $upd_data['id'] = $cwg_row['id']; - Database::pexecute($upd_stmt, $upd_data); - } - $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers were missing the local froxlor-user as group-member, integrity-check fixed that"); - } else { - return false; - } - } + while ($cwg_row = $cwg_stmt->fetch()) { + $upd_data['id'] = $cwg_row['id']; + Database::pexecute($upd_stmt, $upd_data); + } + $this->_log->logAction(ADM_ACTION, LOG_NOTICE, "Customers were missing the local froxlor-user as group-member, integrity-check fixed that"); + } else { + return false; + } + } - if ($fix) { - return $this->FroxlorLocalGroupMemberForFcgidPhpFpm(); - } - return true; + if ($fix) { + return $this->FroxlorLocalGroupMemberForFcgidPhpFpm(); + } + return true; } } diff --git a/lib/Froxlor/FroxlorTwoFactorAuth.php b/lib/Froxlor/FroxlorTwoFactorAuth.php new file mode 100644 index 00000000..7a0f5d01 --- /dev/null +++ b/lib/Froxlor/FroxlorTwoFactorAuth.php @@ -0,0 +1,21 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package API + * @since 0.10.0 + * + */ +class FroxlorTwoFactorAuth extends \RobThree\Auth\TwoFactorAuth +{ +} diff --git a/lib/classes/2FA/.gitignore b/lib/classes/2FA/.gitignore deleted file mode 100644 index 8a25841c..00000000 --- a/lib/classes/2FA/.gitignore +++ /dev/null @@ -1,189 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -build/ -bld/ -[Bb]in/ -[Oo]bj/ - -# Roslyn cache directories -*.ide/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -#NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding addin-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# If using the old MSBuild-Integrated Package Restore, uncomment this: -#!**/packages/repositories.config - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# Composer -/vendor - -# .vs -.vs/ \ No newline at end of file diff --git a/lib/classes/2FA/class.FroxlorTwoFactorAuth.php b/lib/classes/2FA/class.FroxlorTwoFactorAuth.php deleted file mode 100644 index b22700dc..00000000 --- a/lib/classes/2FA/class.FroxlorTwoFactorAuth.php +++ /dev/null @@ -1,38 +0,0 @@ - (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package API - * @since 0.10.0 - * - */ -require_once __DIR__ . '/lib/TwoFactorAuthException.php'; -require_once __DIR__ . '/lib/Providers/Rng/RNGException.php'; -require_once __DIR__ . '/lib/Providers/Rng/IRNGProvider.php'; -require_once __DIR__ . '/lib/Providers/Rng/CSRNGProvider.php'; -require_once __DIR__ . '/lib/Providers/Rng/HashRNGProvider.php'; -require_once __DIR__ . '/lib/Providers/Rng/MCryptRNGProvider.php'; -require_once __DIR__ . '/lib/Providers/Rng/OpenSSLRNGProvider.php'; -require_once __DIR__ . '/lib/Providers/Qr/QRException.php'; -require_once __DIR__ . '/lib/Providers/Qr/IQRCodeProvider.php'; -require_once __DIR__ . '/lib/Providers/Qr/BaseHTTPQRCodeProvider.php'; -require_once __DIR__ . '/lib/Providers/Qr/GoogleQRCodeProvider.php'; -require_once __DIR__ . '/lib/Providers/Time/TimeException.php'; -require_once __DIR__ . '/lib/Providers/Time/ITimeProvider.php'; -require_once __DIR__ . '/lib/Providers/Time/LocalMachineTimeProvider.php'; -require_once __DIR__ . '/lib/Providers/Time/HttpTimeProvider.php'; -require_once __DIR__ . '/lib/Providers/Time/NTPTimeProvider.php'; -require_once __DIR__ . '/lib/TwoFactorAuth.php'; - -class FroxlorTwoFactorAuth extends \RobThree\Auth\TwoFactorAuth -{ -} diff --git a/lib/classes/2FA/lib/Providers/Qr/BaseHTTPQRCodeProvider.php b/lib/classes/2FA/lib/Providers/Qr/BaseHTTPQRCodeProvider.php deleted file mode 100644 index 5cb3adda..00000000 --- a/lib/classes/2FA/lib/Providers/Qr/BaseHTTPQRCodeProvider.php +++ /dev/null @@ -1,27 +0,0 @@ - $url, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_DNS_CACHE_TIMEOUT => 10, - CURLOPT_TIMEOUT => 10, - CURLOPT_SSL_VERIFYPEER => $this->verifyssl, - CURLOPT_USERAGENT => 'TwoFactorAuth' - )); - $data = curl_exec($curlhandle); - - curl_close($curlhandle); - return $data; - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Qr/GoogleQRCodeProvider.php b/lib/classes/2FA/lib/Providers/Qr/GoogleQRCodeProvider.php deleted file mode 100644 index 1b77ae99..00000000 --- a/lib/classes/2FA/lib/Providers/Qr/GoogleQRCodeProvider.php +++ /dev/null @@ -1,39 +0,0 @@ -verifyssl = $verifyssl; - - $this->errorcorrectionlevel = $errorcorrectionlevel; - $this->margin = $margin; - } - - public function getMimeType() - { - return 'image/png'; - } - - public function getQRCodeImage($qrtext, $size) - { - return $this->getContent($this->getUrl($qrtext, $size)); - } - - public function getUrl($qrtext, $size) - { - return 'https://www.google.com/chart?cht=qr' - . '&chs=' . $size . 'x' . $size - . '&chld=' . $this->errorcorrectionlevel . '|' . $this->margin - . '&chl=' . rawurlencode($qrtext); - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Qr/IQRCodeProvider.php b/lib/classes/2FA/lib/Providers/Qr/IQRCodeProvider.php deleted file mode 100644 index 83ed67ba..00000000 --- a/lib/classes/2FA/lib/Providers/Qr/IQRCodeProvider.php +++ /dev/null @@ -1,9 +0,0 @@ -verifyssl = $verifyssl; - - $this->errorcorrectionlevel = $errorcorrectionlevel; - $this->margin = $margin; - $this->qzone = $qzone; - $this->bgcolor = $bgcolor; - $this->color = $color; - $this->format = $format; - } - - public function getMimeType() - { - switch (strtolower($this->format)) - { - case 'png': - return 'image/png'; - case 'gif': - return 'image/gif'; - case 'jpg': - case 'jpeg': - return 'image/jpeg'; - case 'svg': - return 'image/svg+xml'; - case 'eps': - return 'application/postscript'; - } - throw new \QRException(sprintf('Unknown MIME-type: %s', $this->format)); - } - - public function getQRCodeImage($qrtext, $size) - { - return $this->getContent($this->getUrl($qrtext, $size)); - } - - private function decodeColor($value) - { - return vsprintf('%d-%d-%d', sscanf($value, "%02x%02x%02x")); - } - - public function getUrl($qrtext, $size) - { - return 'https://api.qrserver.com/v1/create-qr-code/' - . '?size=' . $size . 'x' . $size - . '&ecc=' . strtoupper($this->errorcorrectionlevel) - . '&margin=' . $this->margin - . '&qzone=' . $this->qzone - . '&bgcolor=' . $this->decodeColor($this->bgcolor) - . '&color=' . $this->decodeColor($this->color) - . '&format=' . strtolower($this->format) - . '&data=' . rawurlencode($qrtext); - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Qr/QRicketProvider.php b/lib/classes/2FA/lib/Providers/Qr/QRicketProvider.php deleted file mode 100644 index 59e27ccd..00000000 --- a/lib/classes/2FA/lib/Providers/Qr/QRicketProvider.php +++ /dev/null @@ -1,54 +0,0 @@ -verifyssl = false; - - $this->errorcorrectionlevel = $errorcorrectionlevel; - $this->bgcolor = $bgcolor; - $this->color = $color; - $this->format = $format; - } - - public function getMimeType() - { - switch (strtolower($this->format)) - { - case 'p': - return 'image/png'; - case 'g': - return 'image/gif'; - case 'j': - return 'image/jpeg'; - } - throw new \QRException(sprintf('Unknown MIME-type: %s', $this->format)); - } - - public function getQRCodeImage($qrtext, $size) - { - return $this->getContent($this->getUrl($qrtext, $size)); - } - - public function getUrl($qrtext, $size) - { - return 'http://qrickit.com/api/qr' - . '?qrsize=' . $size - . '&e=' . strtolower($this->errorcorrectionlevel) - . '&bgdcolor=' . $this->bgcolor - . '&fgdcolor=' . $this->color - . '&t=' . strtolower($this->format) - . '&d=' . rawurlencode($qrtext); - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Rng/CSRNGProvider.php b/lib/classes/2FA/lib/Providers/Rng/CSRNGProvider.php deleted file mode 100644 index 8dba7fc9..00000000 --- a/lib/classes/2FA/lib/Providers/Rng/CSRNGProvider.php +++ /dev/null @@ -1,14 +0,0 @@ -algorithm = $algorithm; - } - - public function getRandomBytes($bytecount) { - $result = ''; - $hash = mt_rand(); - for ($i = 0; $i < $bytecount; $i++) { - $hash = hash($this->algorithm, $hash.mt_rand(), true); - $result .= $hash[mt_rand(0, strlen($hash)-1)]; - } - return $result; - } - - public function isCryptographicallySecure() { - return false; - } -} diff --git a/lib/classes/2FA/lib/Providers/Rng/IRNGProvider.php b/lib/classes/2FA/lib/Providers/Rng/IRNGProvider.php deleted file mode 100644 index 6be28006..00000000 --- a/lib/classes/2FA/lib/Providers/Rng/IRNGProvider.php +++ /dev/null @@ -1,9 +0,0 @@ -source = $source; - } - - public function getRandomBytes($bytecount) { - $result = @mcrypt_create_iv($bytecount, $this->source); - if ($result === false) - throw new \RNGException('mcrypt_create_iv returned an invalid value'); - return $result; - } - - public function isCryptographicallySecure() { - return true; - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Rng/OpenSSLRNGProvider.php b/lib/classes/2FA/lib/Providers/Rng/OpenSSLRNGProvider.php deleted file mode 100644 index dc66c64a..00000000 --- a/lib/classes/2FA/lib/Providers/Rng/OpenSSLRNGProvider.php +++ /dev/null @@ -1,25 +0,0 @@ -requirestrong = $requirestrong; - } - - public function getRandomBytes($bytecount) { - $result = openssl_random_pseudo_bytes($bytecount, $crypto_strong); - if ($this->requirestrong && ($crypto_strong === false)) - throw new \RNGException('openssl_random_pseudo_bytes returned non-cryptographically strong value'); - if ($result === false) - throw new \RNGException('openssl_random_pseudo_bytes returned an invalid value'); - return $result; - } - - public function isCryptographicallySecure() { - return $this->requirestrong; - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Rng/RNGException.php b/lib/classes/2FA/lib/Providers/Rng/RNGException.php deleted file mode 100644 index eb5e913d..00000000 --- a/lib/classes/2FA/lib/Providers/Rng/RNGException.php +++ /dev/null @@ -1,5 +0,0 @@ -url = $url; - $this->expectedtimeformat = $expectedtimeformat; - $this->options = $options; - if ($this->options === null) { - $this->options = array( - 'http' => array( - 'method' => 'HEAD', - 'follow_location' => false, - 'ignore_errors' => true, - 'max_redirects' => 0, - 'request_fulluri' => true, - 'header' => array( - 'Connection: close', - 'User-agent: TwoFactorAuth HttpTimeProvider (https://github.com/RobThree/TwoFactorAuth)', - 'Cache-Control: no-cache' - ) - ) - ); - } - } - - public function getTime() { - try { - $context = stream_context_create($this->options); - $fd = fopen($this->url, 'rb', false, $context); - $headers = stream_get_meta_data($fd); - fclose($fd); - - foreach ($headers['wrapper_data'] as $h) { - if (strcasecmp(substr($h, 0, 5), 'Date:') === 0) - return \DateTime::createFromFormat($this->expectedtimeformat, trim(substr($h,5)))->getTimestamp(); - } - throw new \TimeException(sprintf('Unable to retrieve time from %s (Invalid or no "Date:" header found)', $this->url)); - } - catch (Exception $ex) { - throw new \TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->url, $ex->getMessage())); - } - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Time/ITimeProvider.php b/lib/classes/2FA/lib/Providers/Time/ITimeProvider.php deleted file mode 100644 index a3b87a20..00000000 --- a/lib/classes/2FA/lib/Providers/Time/ITimeProvider.php +++ /dev/null @@ -1,8 +0,0 @@ -host = $host; - - if (!is_int($port) || $port <= 0 || $port > 65535) - throw new \TimeException('Port must be 0 < port < 65535'); - $this->port = $port; - - if (!is_int($timeout) || $timeout < 0) - throw new \TimeException('Timeout must be >= 0'); - $this->timeout = $timeout; - } - - public function getTime() { - try { - /* Create a socket and connect to NTP server */ - $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); - socket_connect($sock, $this->host, $this->port); - - /* Send request */ - $msg = "\010" . str_repeat("\0", 47); - socket_send($sock, $msg, strlen($msg), 0); - - /* Receive response and close socket */ - socket_recv($sock, $recv, 48, MSG_WAITALL); - socket_close($sock); - - /* Interpret response */ - $data = unpack('N12', $recv); - $timestamp = sprintf('%u', $data[9]); - - /* NTP is number of seconds since 0000 UT on 1 January 1900 Unix time is seconds since 0000 UT on 1 January 1970 */ - return $timestamp - 2208988800; - } - catch (Exception $ex) { - throw new \TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->host, $ex->getMessage())); - } - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/Providers/Time/TimeException.php b/lib/classes/2FA/lib/Providers/Time/TimeException.php deleted file mode 100644 index 8de544d0..00000000 --- a/lib/classes/2FA/lib/Providers/Time/TimeException.php +++ /dev/null @@ -1,5 +0,0 @@ -issuer = $issuer; - if (!is_int($digits) || $digits <= 0) - throw new TwoFactorAuthException('Digits must be int > 0'); - $this->digits = $digits; - - if (!is_int($period) || $period <= 0) - throw new TwoFactorAuthException('Period must be int > 0'); - $this->period = $period; - - $algorithm = strtolower(trim($algorithm)); - if (!in_array($algorithm, self::$_supportedalgos)) - throw new TwoFactorAuthException('Unsupported algorithm: ' . $algorithm); - $this->algorithm = $algorithm; - $this->qrcodeprovider = $qrcodeprovider; - $this->rngprovider = $rngprovider; - $this->timeprovider = $timeprovider; - - self::$_base32 = str_split(self::$_base32dict); - self::$_base32lookup = array_flip(self::$_base32); - } - - /** - * Create a new secret - */ - public function createSecret($bits = 80, $requirecryptosecure = true) - { - $secret = ''; - $bytes = ceil($bits / 5); //We use 5 bits of each byte (since we have a 32-character 'alphabet' / BASE32) - $rngprovider = $this->getRngprovider(); - if ($requirecryptosecure && !$rngprovider->isCryptographicallySecure()) - throw new TwoFactorAuthException('RNG provider is not cryptographically secure'); - $rnd = $rngprovider->getRandomBytes($bytes); - for ($i = 0; $i < $bytes; $i++) - $secret .= self::$_base32[ord($rnd[$i]) & 31]; //Mask out left 3 bits for 0-31 values - return $secret; - } - - /** - * Calculate the code with given secret and point in time - */ - public function getCode($secret, $time = null) - { - $secretkey = $this->base32Decode($secret); - - $timestamp = chr(0).chr(0).chr(0).chr(0) . pack('N*', $this->getTimeSlice($this->getTime($time))); // Pack time into binary string - $hashhmac = hash_hmac($this->algorithm, $timestamp, $secretkey, true); // Hash it with users secret key - $hashpart = substr($hashhmac, ord(substr($hashhmac, -1)) & 0x0F, 4); // Use last nibble of result as index/offset and grab 4 bytes of the result - $value = unpack('N', $hashpart); // Unpack binary value - $value = $value[1] & 0x7FFFFFFF; // Drop MSB, keep only 31 bits - - return str_pad($value % pow(10, $this->digits), $this->digits, '0', STR_PAD_LEFT); - } - - /** - * Check if the code is correct. This will accept codes starting from ($discrepancy * $period) sec ago to ($discrepancy * period) sec from now - */ - public function verifyCode($secret, $code, $discrepancy = 1, $time = null, &$timeslice = 0) - { - $timetamp = $this->getTime($time); - - $timeslice = 0; - - // To keep safe from timing-attacks we iterate *all* possible codes even though we already may have - // verified a code is correct. We use the timeslice variable to hold either 0 (no match) or the timeslice - // of the match. Each iteration we either set the timeslice variable to the timeslice of the match - // or set the value to itself. This is an effort to maintain constant execution time for the code. - for ($i = -$discrepancy; $i <= $discrepancy; $i++) { - $ts = $timetamp + ($i * $this->period); - $slice = $this->getTimeSlice($ts); - $timeslice = $this->codeEquals($this->getCode($secret, $ts), $code) ? $slice : $timeslice; - } - - return $timeslice > 0; - } - - /** - * Timing-attack safe comparison of 2 codes (see http://blog.ircmaxell.com/2014/11/its-all-about-time.html) - */ - private function codeEquals($safe, $user) { - if (function_exists('hash_equals')) { - return hash_equals($safe, $user); - } - // In general, it's not possible to prevent length leaks. So it's OK to leak the length. The important part is that - // we don't leak information about the difference of the two strings. - if (strlen($safe)===strlen($user)) { - $result = 0; - for ($i = 0; $i < strlen($safe); $i++) - $result |= (ord($safe[$i]) ^ ord($user[$i])); - return $result === 0; - } - return false; - } - - /** - * Get data-uri of QRCode - */ - public function getQRCodeImageAsDataUri($label, $secret, $size = 200) - { - if (!is_int($size) || $size <= 0) - throw new TwoFactorAuthException('Size must be int > 0'); - - $qrcodeprovider = $this->getQrCodeProvider(); - return 'data:' - . $qrcodeprovider->getMimeType() - . ';base64,' - . base64_encode($qrcodeprovider->getQRCodeImage($this->getQRText($label, $secret), $size)); - } - - /** - * Compare default timeprovider with specified timeproviders and ensure the time is within the specified number of seconds (leniency) - */ - public function ensureCorrectTime(array $timeproviders = null, $leniency = 5) - { - if ($timeproviders != null && !is_array($timeproviders)) - throw new TwoFactorAuthException('No timeproviders specified'); - - if ($timeproviders == null) - $timeproviders = array( - new Providers\Time\NTPTimeProvider(), - new Providers\Time\HttpTimeProvider() - ); - - // Get default time provider - $timeprovider = $this->getTimeProvider(); - - // Iterate specified time providers - foreach ($timeproviders as $t) { - if (!($t instanceof ITimeProvider)) - throw new TwoFactorAuthException('Object does not implement ITimeProvider'); - - // Get time from default time provider and compare to specific time provider and throw if time difference is more than specified number of seconds leniency - if (abs($timeprovider->getTime() - $t->getTime()) > $leniency) - throw new TwoFactorAuthException(sprintf('Time for timeprovider is off by more than %d seconds when compared to %s', $leniency, get_class($t))); - } - } - - private function getTime($time) - { - return ($time === null) ? $this->getTimeProvider()->getTime() : $time; - } - - private function getTimeSlice($time = null, $offset = 0) - { - return (int)floor($time / $this->period) + ($offset * $this->period); - } - - /** - * Builds a string to be encoded in a QR code - */ - public function getQRText($label, $secret) - { - return 'otpauth://totp/' . rawurlencode($label) - . '?secret=' . rawurlencode($secret) - . '&issuer=' . rawurlencode($this->issuer) - . '&period=' . intval($this->period) - . '&algorithm=' . rawurlencode(strtoupper($this->algorithm)) - . '&digits=' . intval($this->digits); - } - - private function base32Decode($value) - { - if (strlen($value)==0) return ''; - - if (preg_match('/[^'.preg_quote(self::$_base32dict).']/', $value) !== 0) - throw new TwoFactorAuthException('Invalid base32 string'); - - $buffer = ''; - foreach (str_split($value) as $char) - { - if ($char !== '=') - $buffer .= str_pad(decbin(self::$_base32lookup[$char]), 5, 0, STR_PAD_LEFT); - } - $length = strlen($buffer); - $blocks = trim(chunk_split(substr($buffer, 0, $length - ($length % 8)), 8, ' ')); - - $output = ''; - foreach (explode(' ', $blocks) as $block) - $output .= chr(bindec(str_pad($block, 8, 0, STR_PAD_RIGHT))); - return $output; - } - - /** - * @return IQRCodeProvider - * @throws TwoFactorAuthException - */ - public function getQrCodeProvider() - { - // Set default QR Code provider if none was specified - if (null === $this->qrcodeprovider) { - return $this->qrcodeprovider = new Providers\Qr\GoogleQRCodeProvider(); - } - return $this->qrcodeprovider; - } - - /** - * @return IRNGProvider - * @throws TwoFactorAuthException - */ - public function getRngprovider() - { - if (null !== $this->rngprovider) { - return $this->rngprovider; - } - if (function_exists('random_bytes')) { - return $this->rngprovider = new Providers\Rng\CSRNGProvider(); - } - if (function_exists('mcrypt_create_iv')) { - return $this->rngprovider = new Providers\Rng\MCryptRNGProvider(); - } - if (function_exists('openssl_random_pseudo_bytes')) { - return $this->rngprovider = new Providers\Rng\OpenSSLRNGProvider(); - } - if (function_exists('hash')) { - return $this->rngprovider = new Providers\Rng\HashRNGProvider(); - } - throw new TwoFactorAuthException('Unable to find a suited RNGProvider'); - } - - /** - * @return ITimeProvider - * @throws TwoFactorAuthException - */ - public function getTimeProvider() - { - // Set default time provider if none was specified - if (null === $this->timeprovider) { - return $this->timeprovider = new Providers\Time\LocalMachineTimeProvider(); - } - return $this->timeprovider; - } -} \ No newline at end of file diff --git a/lib/classes/2FA/lib/TwoFactorAuthException.php b/lib/classes/2FA/lib/TwoFactorAuthException.php deleted file mode 100644 index af51b748..00000000 --- a/lib/classes/2FA/lib/TwoFactorAuthException.php +++ /dev/null @@ -1,7 +0,0 @@ - (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Functions - * - */ -