mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
Merge branch 'MDL-55404-master' of git://github.com/cameron1729/moodle
This commit is contained in:
commit
6658ef6cd9
@ -1846,6 +1846,11 @@
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_tls_libraries" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tlswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
@ -1080,6 +1080,7 @@ $string['timezoneisforcedto'] = 'Force all users to use';
|
||||
$string['timezonenotforced'] = 'Users can choose their own timezone';
|
||||
$string['timezonephpdefault'] = 'Default PHP timezone ({$a})';
|
||||
$string['timezoneserver'] = 'Server timezone ({$a})';
|
||||
$string['tlswarning'] = 'No PHP/cURL extension with TLSv1.2 support has been detected. Some services may not work. It is strongly recommentd that you upgrade your TLS libraries.';
|
||||
$string['tokenizerrecommended'] = 'Installing the optional PHP Tokenizer extension is recommended -- it improves Moodle Networking functionality.';
|
||||
$string['tools'] = 'Admin tools';
|
||||
$string['toolsmanage'] = 'Manage admin tools';
|
||||
|
115
lib/classes/upgrade/util.php
Normal file
115
lib/classes/upgrade/util.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* PayPal enrolment plugin utility class.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core\upgrade;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Core upgrade utility class.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class util {
|
||||
|
||||
/**
|
||||
* Gets the minimum version of a SSL/TLS library required for TLS 1.2 support.
|
||||
*
|
||||
* @param string $sslflavour The SSL/TLS library
|
||||
* @return string|false The version string if it exists. False otherwise
|
||||
*/
|
||||
private static function get_min_ssl_lib_version_for_tls12($sslflavour) {
|
||||
// Min versions for TLS 1.2.
|
||||
$versionmatrix = [
|
||||
'OpenSSL' => '1.0.1c',
|
||||
'GnuTLS' => '1.7.1',
|
||||
'NSS' => '3.15.1', // This number is usually followed by something like "Basic ECC".
|
||||
'CyaSSL' => '1.1.0',
|
||||
'wolfSSL' => '1.1.0',
|
||||
'PolarSSL' => '1.2.0',
|
||||
'WinSSL' => '*', // Does not specify a version but needs Windows >= 7.
|
||||
'SecureTransport' => '*' // Does not specify a version but needs iOS >= 5.0 or OS X >= 10.8.0.
|
||||
];
|
||||
|
||||
return isset($versionmatrix[$sslflavour]) ? $versionmatrix[$sslflavour] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates PHP/cURL extension for use with SSL/TLS.
|
||||
*
|
||||
* @param array $curlinfo array of cURL information as returned by curl_version()
|
||||
* @param int $zts 0 or 1 as defined by PHP_ZTS
|
||||
* @return bool
|
||||
*/
|
||||
public static function validate_php_curl_tls(array $curlinfo, $zts) {
|
||||
if (empty($curlinfo['ssl_version'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$flavour = explode('/', $curlinfo['ssl_version'])[0];
|
||||
// In threadsafe mode the only valid choices are OpenSSL and GnuTLS.
|
||||
if ($zts === 1 && $flavour != 'OpenSSL' && $flavour !== 'GnuTLS') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the system is capable of using TLS 1.2 for requests.
|
||||
*
|
||||
* @param array $curlinfo array of cURL information as returned by curl_version()
|
||||
* @param string $uname server uname
|
||||
* @return bool
|
||||
*/
|
||||
public static function can_use_tls12(array $curlinfo, $uname) {
|
||||
if ($curlinfo['version_number'] < 467456 || !defined('CURL_SSLVERSION_TLSv1_2')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sslversion = explode('/', $curlinfo['ssl_version']);
|
||||
// NSS has a space in the version number 😦.
|
||||
$flavour = explode(' ', $sslversion[0])[0];
|
||||
$version = count($sslversion) == 2 ? $sslversion[1] : null;
|
||||
|
||||
$minversion = self::get_min_ssl_lib_version_for_tls12($flavour);
|
||||
if (!$minversion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special case (see $versionmatrix above).
|
||||
if ($flavour == 'WinSSL') {
|
||||
return $uname >= '6.1';
|
||||
}
|
||||
|
||||
// Special case (see $versionmatrix above).
|
||||
if ($flavour == 'SecureTransport') {
|
||||
return $uname >= '10.8.0';
|
||||
}
|
||||
|
||||
return $version >= $minversion;
|
||||
}
|
||||
}
|
@ -40,6 +40,8 @@ class core_environment_testcase extends advanced_testcase {
|
||||
require_once($CFG->libdir.'/environmentlib.php');
|
||||
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($CFG->release), ENV_SELECT_RELEASE);
|
||||
|
||||
$sslmessages = ['ssl/tls configuration not supported', 'invalid ssl/tls configuration'];
|
||||
|
||||
$this->assertNotEmpty($envstatus);
|
||||
foreach ($environment_results as $environment_result) {
|
||||
if ($environment_result->part === 'php_setting'
|
||||
@ -50,6 +52,14 @@ class core_environment_testcase extends advanced_testcase {
|
||||
$this->markTestSkipped('OPCache extension is not necessary for unit testing.');
|
||||
continue;
|
||||
}
|
||||
if ($environment_result->part === 'custom_check'
|
||||
and in_array($environment_result->info, $sslmessages)
|
||||
and $environment_result->getLevel() === 'optional'
|
||||
and $environment_result->getStatus() === false
|
||||
) {
|
||||
$this->markTestSkipped('Up-to-date TLS libraries are not necessary for unit testing.');
|
||||
continue;
|
||||
}
|
||||
$this->assertTrue($environment_result->getStatus(), "Problem detected in environment ($environment_result->part:$environment_result->info), fix all warnings and errors!");
|
||||
}
|
||||
}
|
||||
|
183
lib/tests/upgrade_util_test.php
Normal file
183
lib/tests/upgrade_util_test.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Upgrade utility class tests.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Upgrade utility class tests.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class upgrade_util_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* A cURL version that supports TLS 1.2.
|
||||
*/
|
||||
const VALID_CURL_VERSION = 467456;
|
||||
|
||||
/**
|
||||
* A cURL version that does not support TLS 1.2.
|
||||
*/
|
||||
const INVALID_CURL_VERSION = 467455;
|
||||
|
||||
/**
|
||||
* The value of PHP_ZTS when thread safety is enabled.
|
||||
*/
|
||||
const PHP_ZTS_ENABLED = 1;
|
||||
|
||||
/**
|
||||
* The value of PHP_ZTS when thread safety is disabled.
|
||||
*/
|
||||
const PHP_ZTS_DISABLED = 0;
|
||||
|
||||
/**
|
||||
* Test PHP/cURL validation.
|
||||
*
|
||||
* @dataProvider validate_php_curl_tls_testcases()
|
||||
* @param array $curlinfo server curl_version array
|
||||
* @param int $zts 0 or 1 as defined by PHP_ZTS
|
||||
* @param bool $expected expected result
|
||||
*/
|
||||
public function test_validate_php_curl_tls($curlinfo, $zts, $expected) {
|
||||
$expected === true && $this->assertTrue(\core\upgrade\util::validate_php_curl_tls($curlinfo, $zts));
|
||||
$expected === false && $this->assertFalse(\core\upgrade\util::validate_php_curl_tls($curlinfo, $zts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for validate_php_curl_tls test.
|
||||
*/
|
||||
public function validate_php_curl_tls_testcases() {
|
||||
$base = curl_version();
|
||||
|
||||
return [
|
||||
'Not threadsafe - Valid SSL (GnuTLS)' => [
|
||||
['ssl_version' => 'GnuTLS/4.20'] + $base,
|
||||
self::PHP_ZTS_DISABLED,
|
||||
true
|
||||
],
|
||||
'Not threadsafe - Valid SSL (OpenSSL)' => [
|
||||
['ssl_version' => 'OpenSSL'] + $base,
|
||||
self::PHP_ZTS_DISABLED,
|
||||
true
|
||||
],
|
||||
'Not threadsafe - Valid SSL (WinSSL)' => [
|
||||
['ssl_version' => 'WinSSL'] + $base,
|
||||
self::PHP_ZTS_DISABLED,
|
||||
true
|
||||
],
|
||||
'Not threadsafe - Invalid SSL' => [
|
||||
['ssl_version' => ''] + $base,
|
||||
self::PHP_ZTS_DISABLED,
|
||||
false
|
||||
],
|
||||
'Threadsafe - Valid SSL (OpenSSL)' => [
|
||||
['ssl_version' => 'OpenSSL/1729'] + $base,
|
||||
self::PHP_ZTS_ENABLED,
|
||||
true
|
||||
],
|
||||
'Threadsafe - Valid SSL (GnuTLS)' => [
|
||||
['ssl_version' => 'GnuTLS/3.14'] + $base,
|
||||
self::PHP_ZTS_ENABLED,
|
||||
true
|
||||
],
|
||||
'Threadsafe - Invalid SSL' => [
|
||||
['ssl_version' => ''] + $base,
|
||||
self::PHP_ZTS_ENABLED,
|
||||
false
|
||||
],
|
||||
'Threadsafe - Invalid SSL (but not empty)' => [
|
||||
['ssl_version' => 'Not GnuTLS or OpenSSL'] + $base,
|
||||
self::PHP_ZTS_ENABLED,
|
||||
false
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various combinations of SSL/TLS libraries.
|
||||
*
|
||||
* @dataProvider can_use_tls12_testcases
|
||||
* @param array $environment the server environment
|
||||
* @param bool $expected expected result
|
||||
*/
|
||||
public function test_can_use_tls12($environment, $expected) {
|
||||
$curlinfo = $environment['curl_version'] + curl_version();
|
||||
|
||||
if ($curlinfo['version_number'] >= self::VALID_CURL_VERSION && !defined('CURL_SSLVERSION_TLSv1_2')) {
|
||||
define('CURL_SSLVERSION_TLSv1_2', 6);
|
||||
}
|
||||
|
||||
$expected === true && $this->assertTrue(\core\upgrade\util::can_use_tls12($curlinfo, $environment['uname']));
|
||||
$expected === false && $this->assertFalse(\core\upgrade\util::can_use_tls12($curlinfo, $environment['uname']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for the can_use_tls test.
|
||||
*
|
||||
* @return array of testcases
|
||||
*/
|
||||
public function can_use_tls12_testcases() {
|
||||
$versionmatrix = [
|
||||
'OpenSSL' => ['Older' => '0.9.8o', 'Min required' => '1.0.1c', 'Newer' => '1.0.1t'],
|
||||
'GnuTLS' => ['Older' => '1.5.0', 'Min requires' => '1.7.1', 'Newer' => '1.8.1'],
|
||||
'NSS' => ['Older' => '3.14.15', 'Min required' => '3.15.1 Basic ECC', 'Newer' => '3.17.2 Basic ECC'],
|
||||
'CyaSSL' => ['Older' => '0.9.9', 'Min required' => '1.1.0', 'Newer' => '1.2.0'],
|
||||
'wolfSSL' => ['Older' => '1.0.0', 'Min required' => '1.1.0', 'Newer' => '1.2.0'],
|
||||
'WinSSL' => ['Older' => '5.1', 'Min required' => '6.1', 'Newer' => '7.0'],
|
||||
'SecureTransport' => ['Older' => '10.7.5', 'Min required' => '10.8.0', 'Newer' => '10.9.0']
|
||||
];
|
||||
|
||||
// This will generate an array of testcases from the matrix above.
|
||||
// It generates one testcase for every version. If the version is too
|
||||
// old or the cURL version (passed as an argument) is too old, the
|
||||
// expected result of the testcase is false. Otherwise it is true.
|
||||
//
|
||||
// Each testcase is given a name like WinSSL/Valid env/Min required.
|
||||
// The first part is the SSL/TLS library, the second part is whether
|
||||
// or not the environment is valid (i.e., we are using a valid/invalid
|
||||
// cURL version. The final part says which version of the SSL/TLS library
|
||||
// is being used (i.e., Older, Min required or Newer).
|
||||
$generatetestcases = function($curlversion) use ($versionmatrix) {
|
||||
return array_reduce(array_keys($versionmatrix), function($carry, $sslflavour) use ($versionmatrix, $curlversion) {
|
||||
return $carry + array_reduce(array_keys($versionmatrix[$sslflavour]), function($carry, $sslversion)
|
||||
use ($versionmatrix, $curlversion, $sslflavour) {
|
||||
$env = $curlversion == self::VALID_CURL_VERSION ? 'Valid' : 'Invalid';
|
||||
$exceptions = ['WinSSL', 'SecureTransport'];
|
||||
$versionsuffix = in_array($sslflavour, $exceptions) ? '' : '/' . $versionmatrix[$sslflavour][$sslversion];
|
||||
return $carry + [$sslflavour . '/' . $env. ' env/' . $sslversion => [[
|
||||
'curl_version' => [
|
||||
'ssl_version' => $sslflavour . $versionsuffix,
|
||||
'version_number' => $curlversion
|
||||
],
|
||||
'uname' => in_array($sslflavour, $exceptions) ? $versionmatrix[$sslflavour][$sslversion] : php_uname('r')
|
||||
], $sslversion != 'Older' && $curlversion != self::INVALID_CURL_VERSION]];
|
||||
}, []);
|
||||
}, []);
|
||||
};
|
||||
|
||||
return $generatetestcases(self::VALID_CURL_VERSION) + $generatetestcases(self::INVALID_CURL_VERSION);
|
||||
}
|
||||
}
|
@ -2317,3 +2317,27 @@ function check_unoconv_version(environment_results $result) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for up-to-date TLS libraries.
|
||||
*
|
||||
* @param environment_results $result object to update, if relevant.
|
||||
* @return environment_results|null updated results or null if unoconv path is not executable.
|
||||
*/
|
||||
function check_tls_libraries(environment_results $result) {
|
||||
global $CFG;
|
||||
|
||||
if (!\core\upgrade\util::validate_php_curl_tls(curl_version(), PHP_ZTS)) {
|
||||
$result->setInfo('invalid ssl/tls configuration');
|
||||
$result->setStatus(false);
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (!\core\upgrade\util::can_use_tls12(curl_version(), php_uname('r'))) {
|
||||
$result->setInfo('ssl/tls configuration not supported');
|
||||
$result->setStatus(false);
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user