Commit | Line | Data |
---|---|---|
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 | ||
25 | defined('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 | */ | |
34 | class 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 | } |