MDL-55404 core_upgrade: Add libcurl environment checks
[moodle.git] / lib / tests / upgrade_util_test.php
CommitLineData
ab3759ff
CB
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Upgrade utility class tests.
19 *
20 * @package core
21 * @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27/**
28 * Upgrade utility class tests.
29 *
30 * @package core
31 * @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 */
34class upgrade_util_testcase extends advanced_testcase {
35
36 /**
37 * A cURL version that supports TLS 1.2.
38 */
39 const VALID_CURL_VERSION = 467456;
40
41 /**
42 * A cURL version that does not support TLS 1.2.
43 */
44 const INVALID_CURL_VERSION = 467455;
45
46 /**
47 * The value of PHP_ZTS when thread safety is enabled.
48 */
49 const PHP_ZTS_ENABLED = 1;
50
51 /**
52 * The value of PHP_ZTS when thread safety is disabled.
53 */
54 const PHP_ZTS_DISABLED = 0;
55
56 /**
57 * Test PHP/cURL validation.
58 *
59 * @dataProvider validate_php_curl_tls_testcases()
60 * @param array $curlinfo server curl_version array
61 * @param int $zts 0 or 1 as defined by PHP_ZTS
62 * @param bool $expected expected result
63 */
64 public function test_validate_php_curl_tls($curlinfo, $zts, $expected) {
65 $expected === true && $this->assertTrue(\core\upgrade\util::validate_php_curl_tls($curlinfo, $zts));
66 $expected === false && $this->assertFalse(\core\upgrade\util::validate_php_curl_tls($curlinfo, $zts));
67 }
68
69 /**
70 * Test cases for validate_php_curl_tls test.
71 */
72 public function validate_php_curl_tls_testcases() {
73 $base = curl_version();
74
75 return [
76 'Not threadsafe - Valid SSL (GnuTLS)' => [
77 ['ssl_version' => 'GnuTLS/4.20'] + $base,
78 self::PHP_ZTS_DISABLED,
79 true
80 ],
81 'Not threadsafe - Valid SSL (OpenSSL)' => [
82 ['ssl_version' => 'OpenSSL'] + $base,
83 self::PHP_ZTS_DISABLED,
84 true
85 ],
86 'Not threadsafe - Valid SSL (WinSSL)' => [
87 ['ssl_version' => 'WinSSL'] + $base,
88 self::PHP_ZTS_DISABLED,
89 true
90 ],
91 'Not threadsafe - Invalid SSL' => [
92 ['ssl_version' => ''] + $base,
93 self::PHP_ZTS_DISABLED,
94 false
95 ],
96 'Threadsafe - Valid SSL (OpenSSL)' => [
97 ['ssl_version' => 'OpenSSL/1729'] + $base,
98 self::PHP_ZTS_ENABLED,
99 true
100 ],
101 'Threadsafe - Valid SSL (GnuTLS)' => [
102 ['ssl_version' => 'GnuTLS/3.14'] + $base,
103 self::PHP_ZTS_ENABLED,
104 true
105 ],
106 'Threadsafe - Invalid SSL' => [
107 ['ssl_version' => ''] + $base,
108 self::PHP_ZTS_ENABLED,
109 false
110 ],
111 'Threadsafe - Invalid SSL (but not empty)' => [
112 ['ssl_version' => 'Not GnuTLS or OpenSSL'] + $base,
113 self::PHP_ZTS_ENABLED,
114 false
115 ]
116 ];
117 }
118
119 /**
120 * Test various combinations of SSL/TLS libraries.
121 *
122 * @dataProvider can_use_tls12_testcases
123 * @param array $environment the server environment
124 * @param bool $expected expected result
125 */
126 public function test_can_use_tls12($environment, $expected) {
127 $curlinfo = $environment['curl_version'] + curl_version();
128
129 if ($curlinfo['version_number'] >= self::VALID_CURL_VERSION && !defined('CURL_SSLVERSION_TLSv1_2')) {
130 define('CURL_SSLVERSION_TLSv1_2', 6);
131 }
132
133 $expected === true && $this->assertTrue(\core\upgrade\util::can_use_tls12($curlinfo, $environment['uname']));
134 $expected === false && $this->assertFalse(\core\upgrade\util::can_use_tls12($curlinfo, $environment['uname']));
135 }
136
137 /**
138 * Test cases for the can_use_tls test.
139 *
140 * @return array of testcases
141 */
142 public function can_use_tls12_testcases() {
143 $versionmatrix = [
144 'OpenSSL' => ['Older' => '0.9.8o', 'Min required' => '1.0.1c', 'Newer' => '1.0.1t'],
145 'GnuTLS' => ['Older' => '1.5.0', 'Min requires' => '1.7.1', 'Newer' => '1.8.1'],
146 'NSS' => ['Older' => '3.14.15', 'Min required' => '3.15.1 Basic ECC', 'Newer' => '3.17.2 Basic ECC'],
147 'CyaSSL' => ['Older' => '0.9.9', 'Min required' => '1.1.0', 'Newer' => '1.2.0'],
148 'wolfSSL' => ['Older' => '1.0.0', 'Min required' => '1.1.0', 'Newer' => '1.2.0'],
149 'WinSSL' => ['Older' => '5.1', 'Min required' => '6.1', 'Newer' => '7.0'],
150 'SecureTransport' => ['Older' => '10.7.5', 'Min required' => '10.8.0', 'Newer' => '10.9.0']
151 ];
152
153 // This will generate an array of testcases from the matrix above.
154 // It generates one testcase for every version. If the version is too
155 // old or the cURL version (passed as an argument) is too old, the
156 // expected result of the testcase is false. Otherwise it is true.
157 //
158 // Each testcase is given a name like WinSSL/Valid env/Min required.
159 // The first part is the SSL/TLS library, the second part is whether
160 // or not the environment is valid (i.e., we are using a valid/invalid
161 // cURL version. The final part says which version of the SSL/TLS library
162 // is being used (i.e., Older, Min required or Newer).
163 $generatetestcases = function($curlversion) use ($versionmatrix) {
164 return array_reduce(array_keys($versionmatrix), function($carry, $sslflavour) use ($versionmatrix, $curlversion) {
165 return $carry + array_reduce(array_keys($versionmatrix[$sslflavour]), function($carry, $sslversion)
166 use ($versionmatrix, $curlversion, $sslflavour) {
167 $env = $curlversion == self::VALID_CURL_VERSION ? 'Valid' : 'Invalid';
168 $exceptions = ['WinSSL', 'SecureTransport'];
169 $versionsuffix = in_array($sslflavour, $exceptions) ? '' : '/' . $versionmatrix[$sslflavour][$sslversion];
170 return $carry + [$sslflavour . '/' . $env. ' env/' . $sslversion => [[
171 'curl_version' => [
172 'ssl_version' => $sslflavour . $versionsuffix,
173 'version_number' => $curlversion
174 ],
175 'uname' => in_array($sslflavour, $exceptions) ? $versionmatrix[$sslflavour][$sslversion] : php_uname('r')
176 ], $sslversion != 'Older' && $curlversion != self::INVALID_CURL_VERSION]];
177 }, []);
178 }, []);
179 };
180
181 return $generatetestcases(self::VALID_CURL_VERSION) + $generatetestcases(self::INVALID_CURL_VERSION);
182 }
183}