|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* ***************************************************************************** |
|
5
|
|
|
* Contributions to this work were made on behalf of the GÉANT project, a |
|
6
|
|
|
* project that has received funding from the European Union’s Framework |
|
7
|
|
|
* Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus), |
|
8
|
|
|
* Horizon 2020 research and innovation programme under Grant Agreements No. |
|
9
|
|
|
* 691567 (GN4-1) and No. 731122 (GN4-2). |
|
10
|
|
|
* On behalf of the aforementioned projects, GEANT Association is the sole owner |
|
11
|
|
|
* of the copyright in all material which was developed by a member of the GÉANT |
|
12
|
|
|
* project. GÉANT Vereniging (Association) is registered with the Chamber of |
|
13
|
|
|
* Commerce in Amsterdam with registration number 40535155 and operates in the |
|
14
|
|
|
* UK as a branch of GÉANT Vereniging. |
|
15
|
|
|
* |
|
16
|
|
|
* Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. |
|
17
|
|
|
* UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK |
|
18
|
|
|
* |
|
19
|
|
|
* License: see the web/copyright.inc.php file in the file structure or |
|
20
|
|
|
* <base_url>/copyright.php after deploying the software |
|
21
|
|
|
*/ |
|
22
|
|
|
|
|
23
|
|
|
/** |
|
24
|
|
|
* |
|
25
|
|
|
* |
|
26
|
|
|
* This is the definition of the CAT class implementing various configuration |
|
27
|
|
|
* tests. |
|
28
|
|
|
* Each test is implemented as a priviate method which needs to be named "test_name_test". |
|
29
|
|
|
* The test returns the results by calling the testReturn method, this passing the return |
|
30
|
|
|
* code and the explanatory message. Multiple calls to testReturn are allowed. |
|
31
|
|
|
* |
|
32
|
|
|
* An individual test can be run by the "test" method which takes the test name as an argument |
|
33
|
|
|
* multiple tests should be run by the run_all_tests method which takes an array as an argument |
|
34
|
|
|
* see method descriptions for more information. |
|
35
|
|
|
* |
|
36
|
|
|
* The results of the tests are passed within the $test_result array |
|
37
|
|
|
* |
|
38
|
|
|
* Some configuration of this class is required, see further down. |
|
39
|
|
|
* @author Stefan Winter <[email protected]> |
|
40
|
|
|
* @author Tomasz Wolniewicz <[email protected]> |
|
41
|
|
|
* |
|
42
|
|
|
* @license see LICENSE file in root directory |
|
43
|
|
|
* |
|
44
|
|
|
* @package Utilities |
|
45
|
|
|
*/ |
|
46
|
|
|
|
|
47
|
|
|
namespace core; |
|
48
|
|
|
|
|
49
|
|
|
use GeoIp2\Database\Reader; |
|
50
|
|
|
use \Exception; |
|
51
|
|
|
|
|
52
|
|
|
require_once dirname(dirname(__FILE__)) . "/config/_config.php"; |
|
53
|
|
|
require_once dirname(dirname(__FILE__)) . "/core/PHPMailer/src/PHPMailer.php"; |
|
54
|
|
|
require_once dirname(dirname(__FILE__)) . "/core/PHPMailer/src/SMTP.php"; |
|
55
|
|
|
|
|
56
|
|
|
class SanityTests extends CAT { |
|
57
|
|
|
/* in this section set current CAT requirements */ |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* the minumum required php version |
|
61
|
|
|
* |
|
62
|
|
|
* @var string |
|
63
|
|
|
*/ |
|
64
|
|
|
private $php_needversion = '7.2.0'; |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* the minimum required simpleSAMLphp version |
|
68
|
|
|
* |
|
69
|
|
|
* @var array |
|
70
|
|
|
*/ |
|
71
|
|
|
private $ssp_needversion = ['major' => 1, 'minor' => 15]; |
|
72
|
|
|
|
|
73
|
|
|
/** |
|
74
|
|
|
* all required NSIS modules |
|
75
|
|
|
* |
|
76
|
|
|
* @var array<string> |
|
77
|
|
|
*/ |
|
78
|
|
|
private $NSIS_Modules = [ |
|
79
|
|
|
"nsArray.nsh", |
|
80
|
|
|
"FileFunc.nsh", |
|
81
|
|
|
"LogicLib.nsh", |
|
82
|
|
|
"WordFunc.nsh", |
|
83
|
|
|
"FileFunc.nsh", |
|
84
|
|
|
"x64.nsh", |
|
85
|
|
|
]; |
|
86
|
|
|
|
|
87
|
|
|
/** |
|
88
|
|
|
* set $profile_option_ct to the number of rows returned by |
|
89
|
|
|
* "SELECT * FROM profile_option_dict" |
|
90
|
|
|
* to compare actual vs. expected database structure |
|
91
|
|
|
* |
|
92
|
|
|
* @var integer |
|
93
|
|
|
*/ |
|
94
|
|
|
private $profile_option_ct; |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* set $view_admin_ct to the number of rows returned by "desc view_admin" |
|
98
|
|
|
* |
|
99
|
|
|
* @var integer |
|
100
|
|
|
*/ |
|
101
|
|
|
private $view_admin_ct = 8; |
|
102
|
|
|
|
|
103
|
|
|
/* end of config */ |
|
104
|
|
|
|
|
105
|
|
|
/** |
|
106
|
|
|
* array holding the output of all tests that were executed |
|
107
|
|
|
* |
|
108
|
|
|
* @var array |
|
109
|
|
|
*/ |
|
110
|
|
|
public $out; |
|
111
|
|
|
|
|
112
|
|
|
/** |
|
113
|
|
|
* temporary storage for the name of the test as it is being run |
|
114
|
|
|
* |
|
115
|
|
|
* @var string |
|
116
|
|
|
*/ |
|
117
|
|
|
public $name; |
|
118
|
|
|
|
|
119
|
|
|
/** |
|
120
|
|
|
* initialise the tests. Includes counting the number of expected rows in the profile_option_dict table. |
|
121
|
|
|
*/ |
|
122
|
|
|
public function __construct() { |
|
123
|
|
|
parent::__construct(); |
|
124
|
|
|
$this->test_result = []; |
|
125
|
|
|
$this->test_result['global'] = 0; |
|
126
|
|
|
// parse the schema file to find out the number of expected rows... |
|
127
|
|
|
$schema = file(dirname(dirname(__FILE__)) . "/schema/schema.sql"); |
|
128
|
|
|
$this->profile_option_ct = 0; |
|
129
|
|
|
$passedTheWindmill = FALSE; |
|
130
|
|
|
foreach ($schema as $schemaLine) { |
|
131
|
|
|
if (preg_match("/^INSERT INTO \`profile_option_dict\` VALUES/", $schemaLine)) { |
|
132
|
|
|
$passedTheWindmill = TRUE; |
|
133
|
|
|
continue; |
|
134
|
|
|
} |
|
135
|
|
|
if ($passedTheWindmill) { |
|
136
|
|
|
if (substr($schemaLine, 0, 1) == '(') { // a relevant line in schema |
|
137
|
|
|
$this->profile_option_ct = $this->profile_option_ct + 1; |
|
138
|
|
|
} else { // anything else, quit parsing |
|
139
|
|
|
break; |
|
140
|
|
|
} |
|
141
|
|
|
} |
|
142
|
|
|
} |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* The single test wrapper |
|
147
|
|
|
* @param string $test the test name |
|
148
|
|
|
* @return void |
|
149
|
|
|
*/ |
|
150
|
|
|
public function runTest($test) { |
|
151
|
|
|
$this->out[$test] = []; |
|
152
|
|
|
$this->name = $test; |
|
153
|
|
|
$m_name = 'test' . $test; |
|
154
|
|
|
$this->test_result[$test] = 0; |
|
155
|
|
|
if (!method_exists($this, $m_name)) { |
|
156
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Configuration error, no test configured for <strong>$test</strong>."); |
|
157
|
|
|
return; |
|
158
|
|
|
} |
|
159
|
|
|
$this->$m_name(); |
|
160
|
|
|
} |
|
161
|
|
|
|
|
162
|
|
|
/** |
|
163
|
|
|
* The multiple tests wrapper |
|
164
|
|
|
* @param array $Tests the tests array is a simple string array, where each |
|
165
|
|
|
* entry is a test name. The test names can also be |
|
166
|
|
|
* given in the format "test=>subtest", which defines a |
|
167
|
|
|
* conditional execution of the "subtest" if the "test" |
|
168
|
|
|
* was run earlier and returned a success. |
|
169
|
|
|
* @return void |
|
170
|
|
|
*/ |
|
171
|
|
|
public function runTests($Tests) { |
|
172
|
|
|
foreach ($Tests as $testName) { |
|
173
|
|
|
$matchArray = []; |
|
174
|
|
|
if (preg_match('/(.+)=>(.+)/', $testName, $matchArray)) { |
|
175
|
|
|
$tst = $matchArray[1]; |
|
176
|
|
|
$subtst = $matchArray[2]; |
|
177
|
|
|
if ($this->test_result[$tst] < \core\common\Entity::L_ERROR) { |
|
178
|
|
|
$this->runTest($subtst); |
|
179
|
|
|
} |
|
180
|
|
|
} else { |
|
181
|
|
|
$this->runTest($testName); |
|
182
|
|
|
} |
|
183
|
|
|
} |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
/** |
|
187
|
|
|
* enumerates the tests which are defined |
|
188
|
|
|
* |
|
189
|
|
|
* @return array |
|
190
|
|
|
*/ |
|
191
|
|
|
public function getTestNames() { |
|
192
|
|
|
$T = get_class_methods($this); |
|
193
|
|
|
$out = []; |
|
194
|
|
|
foreach ($T as $t) { |
|
195
|
|
|
if (preg_match('/^test(.*)$/', $t, $m)) { |
|
196
|
|
|
$out[] = $m[1]; |
|
197
|
|
|
} |
|
198
|
|
|
} |
|
199
|
|
|
return $out; |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
/** |
|
203
|
|
|
* This array is used to return the test results. |
|
204
|
|
|
* As the 'global' entry it returns the maximum return value |
|
205
|
|
|
* from all tests. |
|
206
|
|
|
* Individual tests results are teturned as separate entires |
|
207
|
|
|
* indexed by test names; each value is an array passing "level" and "message" |
|
208
|
|
|
* from each of the tests. |
|
209
|
|
|
* $test_result is set by the testReturn method |
|
210
|
|
|
* |
|
211
|
|
|
* @var array $test_result |
|
212
|
|
|
*/ |
|
213
|
|
|
public $test_result; |
|
214
|
|
|
|
|
215
|
|
|
/** |
|
216
|
|
|
* stores the result of a given test in standardised format |
|
217
|
|
|
* |
|
218
|
|
|
* @param int $level severity level of the result |
|
219
|
|
|
* @param string $message verbal description of the result |
|
220
|
|
|
* @return void |
|
221
|
|
|
*/ |
|
222
|
|
|
private function storeTestResult($level, $message) { |
|
223
|
|
|
$this->out[$this->name][] = ['level' => $level, 'message' => $message]; |
|
224
|
|
|
$this->test_result[$this->name] = max($this->test_result[$this->name], $level); |
|
225
|
|
|
$this->test_result['global'] = max($this->test_result['global'], $level); |
|
226
|
|
|
} |
|
227
|
|
|
|
|
228
|
|
|
/** |
|
229
|
|
|
* finds out if a path name is configured as an absolute path or only implicit (e.g. is in $PATH) |
|
230
|
|
|
* @param string $pathToCheck the path to check |
|
231
|
|
|
* @return array |
|
232
|
|
|
*/ |
|
233
|
|
|
private function getExecPath($pathToCheck) { |
|
234
|
|
|
$the_path = ""; |
|
235
|
|
|
$exec_is = "UNDEFINED"; |
|
236
|
|
|
foreach ([CONFIG, CONFIG_CONFASSISTANT, CONFIG_DIAGNOSTICS] as $config) { |
|
237
|
|
|
if (!empty($config['PATHS'][$pathToCheck])) { |
|
238
|
|
|
$matchArray = []; |
|
239
|
|
|
preg_match('/([^ ]+) ?/', $config['PATHS'][$pathToCheck], $matchArray); |
|
240
|
|
|
$exe = $matchArray[1]; |
|
241
|
|
|
$the_path = exec("which " . $config['PATHS'][$pathToCheck]); |
|
242
|
|
|
if ($the_path == $exe) { |
|
243
|
|
|
$exec_is = "EXPLICIT"; |
|
244
|
|
|
} else { |
|
245
|
|
|
$exec_is = "IMPLICIT"; |
|
246
|
|
|
} |
|
247
|
|
|
return(['exec' => $the_path, 'exec_is' => $exec_is]); |
|
248
|
|
|
} |
|
249
|
|
|
} |
|
250
|
|
|
return(['exec' => $the_path, 'exec_is' => $exec_is]); |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
/** |
|
254
|
|
|
* Test for php version |
|
255
|
|
|
* |
|
256
|
|
|
* @return void |
|
257
|
|
|
*/ |
|
258
|
|
|
private function testPhp() { |
|
259
|
|
|
if (version_compare(phpversion(), $this->php_needversion, '>=')) { |
|
260
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "<strong>PHP</strong> is sufficiently recent. You are running " . phpversion() . "."); |
|
261
|
|
|
} else { |
|
262
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>PHP</strong> is too old. We need at least $this->php_needversion, but you only have " . phpversion() . "."); |
|
263
|
|
|
} |
|
264
|
|
|
} |
|
265
|
|
|
|
|
266
|
|
|
/** |
|
267
|
|
|
* set for cat_base_url setting |
|
268
|
|
|
* |
|
269
|
|
|
* @return void |
|
270
|
|
|
*/ |
|
271
|
|
|
private function testCatBaseUrl() { |
|
272
|
|
|
$rootUrl = substr(CONFIG['PATHS']['cat_base_url'], -1) === '/' ? substr(CONFIG['PATHS']['cat_base_url'], 0, -1) : CONFIG['PATHS']['cat_base_url']; |
|
273
|
|
|
preg_match('/(^.*)\/admin\/112365365321.php/', $_SERVER['SCRIPT_NAME'], $m); |
|
274
|
|
|
if ($rootUrl === $m[1]) { |
|
275
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "<strong>cat_base_url</strong> set correctly"); |
|
276
|
|
|
} else { |
|
277
|
|
|
$rootFromScript = $m[1] === '' ? '/' : $m[1]; |
|
278
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>cat_base_url</strong> is set to <strong>" . CONFIG['PATHS']['cat_base_url'] . "</strong> and should be <strong>$rootFromScript</strong>"); |
|
279
|
|
|
} |
|
280
|
|
|
} |
|
281
|
|
|
|
|
282
|
|
|
/** |
|
283
|
|
|
* check whether the configured RADIUS hosts actually exist |
|
284
|
|
|
* |
|
285
|
|
|
* @return void |
|
286
|
|
|
*/ |
|
287
|
|
|
private function testRADIUSProbes() { |
|
288
|
|
|
$probeReturns = []; |
|
289
|
|
|
foreach (CONFIG_DIAGNOSTICS['RADIUSTESTS']['UDP-hosts'] as $oneProbe) { |
|
290
|
|
|
$statusServer = new diag\RFC5997Tests($oneProbe['ip'], 1812, $oneProbe['secret']); |
|
291
|
|
|
if ($statusServer->statusServerCheck() !== diag\AbstractTest::RETVAL_OK) { |
|
292
|
|
|
$probeReturns[] = $oneProbe['display_name']; |
|
293
|
|
|
} |
|
294
|
|
|
} |
|
295
|
|
|
if (count($probeReturns) == 0) { |
|
296
|
|
|
$this->storeTestResult(common\Entity::L_OK, "All configured RADIUS/UDP probes are reachable."); |
|
297
|
|
|
} else { |
|
298
|
|
|
$this->storeTestResult(common\Entity::L_ERROR, "The following RADIUS probes are NOT reachable: ".implode(', ',$probeReturns)); |
|
299
|
|
|
} |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
/** |
|
303
|
|
|
* test for simpleSAMLphp |
|
304
|
|
|
* |
|
305
|
|
|
* @return void |
|
306
|
|
|
*/ |
|
307
|
|
|
private function testSsp() { |
|
308
|
|
|
if (!is_file(CONFIG['AUTHENTICATION']['ssp-path-to-autoloader'])) { |
|
309
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>simpleSAMLphp</strong> not found!"); |
|
310
|
|
|
} else { |
|
311
|
|
|
include_once CONFIG['AUTHENTICATION']['ssp-path-to-autoloader']; |
|
312
|
|
|
$SSPconfig = \SimpleSAML_Configuration::getInstance(); |
|
313
|
|
|
$sspVersion = explode('.', $SSPconfig->getVersion()); |
|
314
|
|
|
if ((int) $sspVersion[0] >= $this->ssp_needversion['major'] && (int) $sspVersion[1] >= $this->ssp_needversion['minor']) { |
|
315
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "<strong>simpleSAMLphp</strong> is sufficently recent. You are running " . implode('.', $sspVersion)); |
|
316
|
|
|
} else { |
|
317
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>simpleSAMLphp</strong> is too old. We need at least " . implode('.', $this->ssp_needversion)); |
|
318
|
|
|
} |
|
319
|
|
|
} |
|
320
|
|
|
} |
|
321
|
|
|
|
|
322
|
|
|
/** |
|
323
|
|
|
* test for security setting |
|
324
|
|
|
* |
|
325
|
|
|
* @return void |
|
326
|
|
|
*/ |
|
327
|
|
|
private function testSecurity() { |
|
328
|
|
|
if (in_array("I do not care about security!", CONFIG['SUPERADMINS'])) { |
|
329
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "You do not care about security. This page should be made accessible to the CAT admin only! See config-master.php: 'SUPERADMINS'!"); |
|
330
|
|
|
} |
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
/** |
|
334
|
|
|
* test if zip is available |
|
335
|
|
|
* |
|
336
|
|
|
* @return void |
|
337
|
|
|
*/ |
|
338
|
|
|
private function testZip() { |
|
339
|
|
|
if (exec("which zip") != "") { |
|
340
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "<strong>zip</strong> binary found."); |
|
341
|
|
|
} else { |
|
342
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>zip</strong> not found in your \$PATH!"); |
|
343
|
|
|
} |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
/** |
|
347
|
|
|
* test if eapol_test is available and recent enough |
|
348
|
|
|
* |
|
349
|
|
|
* @return void |
|
350
|
|
|
*/ |
|
351
|
|
|
private function testEapoltest() { |
|
352
|
|
|
exec(CONFIG_DIAGNOSTICS['PATHS']['eapol_test'], $out, $retval); |
|
353
|
|
|
if ($retval == 255) { |
|
354
|
|
|
$o = preg_grep('/-o<server cert/', $out); |
|
355
|
|
|
if (count($o) > 0) { |
|
356
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "<strong>eapol_test</strong> script found."); |
|
357
|
|
|
} else { |
|
358
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>eapol_test</strong> found, but is too old!"); |
|
359
|
|
|
} |
|
360
|
|
|
} else { |
|
361
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>eapol_test</strong> not found!"); |
|
362
|
|
|
} |
|
363
|
|
|
} |
|
364
|
|
|
|
|
365
|
|
|
/** |
|
366
|
|
|
* test if logdir exists and is writable |
|
367
|
|
|
* |
|
368
|
|
|
* @return void |
|
369
|
|
|
*/ |
|
370
|
|
|
private function testLogdir() { |
|
371
|
|
|
if (fopen(CONFIG['PATHS']['logdir'] . "/debug.log", "a") == FALSE) { |
|
372
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "Log files in <strong>" . CONFIG['PATHS']['logdir'] . "</strong> are not writable!"); |
|
373
|
|
|
} else { |
|
374
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "Log directory is writable."); |
|
375
|
|
|
} |
|
376
|
|
|
} |
|
377
|
|
|
|
|
378
|
|
|
/** |
|
379
|
|
|
* test for required PHP modules |
|
380
|
|
|
* |
|
381
|
|
|
* @return void |
|
382
|
|
|
*/ |
|
383
|
|
|
private function testPhpModules() { |
|
384
|
|
|
if (function_exists('idn_to_ascii')) { |
|
385
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "PHP can handle internationalisation."); |
|
386
|
|
|
} else { |
|
387
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP can <strong>NOT</strong> handle internationalisation (idn_to_ascii() from php7.0-intl)."); |
|
388
|
|
|
} |
|
389
|
|
|
|
|
390
|
|
|
if (function_exists('gettext')) { |
|
391
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "PHP extension <strong>GNU Gettext</strong> is installed."); |
|
392
|
|
|
} else { |
|
393
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GNU Gettext</strong> not found!"); |
|
394
|
|
|
} |
|
395
|
|
|
|
|
396
|
|
|
if (function_exists('openssl_sign')) { |
|
397
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "PHP extension <strong>OpenSSL</strong> is installed."); |
|
398
|
|
|
} else { |
|
399
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>OpenSSL</strong> not found!"); |
|
400
|
|
|
} |
|
401
|
|
|
|
|
402
|
|
|
if (class_exists('\Imagick')) { |
|
403
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "PHP extension <strong>Imagick</strong> is installed."); |
|
404
|
|
|
} else { |
|
405
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>Imagick</strong> not found! Get it from your distribution or <a href='http://pecl.php.net/package/imagick'>here</a>."); |
|
406
|
|
|
} |
|
407
|
|
|
|
|
408
|
|
|
if (function_exists('ImageCreate')) { |
|
409
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "PHP extension <strong>GD</strong> is installed."); |
|
410
|
|
|
} else { |
|
411
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GD</strong> not found!</a>."); |
|
412
|
|
|
} |
|
413
|
|
|
|
|
414
|
|
|
if (function_exists('mysqli_connect')) { |
|
415
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "PHP extension <strong>MySQL</strong> is installed."); |
|
416
|
|
|
} else { |
|
417
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>MySQL</strong> not found!"); |
|
418
|
|
|
} |
|
419
|
|
|
} |
|
420
|
|
|
|
|
421
|
|
|
/** |
|
422
|
|
|
* test if GeoIP is installed correctly |
|
423
|
|
|
* |
|
424
|
|
|
* @return void |
|
425
|
|
|
*/ |
|
426
|
|
|
private function testGeoip() { |
|
427
|
|
|
$host_4 = '145.0.2.50'; |
|
428
|
|
|
$host_6 = '2001:610:188:444::50'; |
|
429
|
|
|
switch (CONFIG['GEOIP']['version']) { |
|
430
|
|
|
case 0: |
|
431
|
|
|
$this->storeTestResult(\core\common\Entity::L_REMARK, "As set in the config, no geolocation service will be used"); |
|
432
|
|
|
break; |
|
433
|
|
|
case 1: |
|
434
|
|
|
if (!function_exists('geoip_record_by_name')) { |
|
435
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP</strong> (legacy) not found! Get it from your distribution or <a href='http://pecl.php.net/package/geoip'>here</a> or better install GeoIP2 from <a href='https://github.com/maxmind/GeoIP2-php'>here</a>."); |
|
436
|
|
|
return; |
|
437
|
|
|
} |
|
438
|
|
|
$record = geoip_record_by_name($host_4); |
|
439
|
|
|
if ($record === FALSE) { |
|
440
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP</strong> (legacy) found but not working properly, perhaps you need to download the databases. See utils/GeoIP-update.sh in the CAT distribution and use it tu update the GeoIP database regularly."); |
|
441
|
|
|
return; |
|
442
|
|
|
} |
|
443
|
|
|
if ($record['city'] != 'Utrecht') { |
|
444
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP</strong> (legacy) found but not working properly, perhaps you need to download the databases. See utils/GeoIP-update.sh in the CAT distribution and use it tu update the GeoIP database regularly."); |
|
445
|
|
|
return; |
|
446
|
|
|
} |
|
447
|
|
|
$this->storeTestResult(\core\common\Entity::L_REMARK, "PHP extension <strong>GeoIP</strong> (legacy) is installed and working. See utils/GeoIP-update.sh in the CAT distribution and use it tu update the GeoIP database regularly. We stronly advise to replace the legacy GeoIP with GeoIP2 from <a href='https://github.com/maxmind/GeoIP2-php'>here</a>."); |
|
448
|
|
|
break; |
|
449
|
|
|
case 2: |
|
450
|
|
|
if (!is_file(CONFIG['GEOIP']['geoip2-path-to-autoloader'])) { |
|
451
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP2</strong> not found! Get it from <a href='https://github.com/maxmind/GeoIP2-php'>here</a>."); |
|
452
|
|
|
return; |
|
453
|
|
|
} |
|
454
|
|
|
if (!is_file(CONFIG['GEOIP']['geoip2-path-to-db'])) { |
|
455
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>GeoIP2 database</strong> not found! See utils/GeoIP-update.sh in the CAT distribution and use it tu update the GeoIP database regularly."); |
|
456
|
|
|
return; |
|
457
|
|
|
} |
|
458
|
|
|
include_once CONFIG['GEOIP']['geoip2-path-to-autoloader']; |
|
459
|
|
|
$reader = new Reader(CONFIG['GEOIP']['geoip2-path-to-db']); |
|
460
|
|
|
try { |
|
461
|
|
|
$record = $reader->city($host_4); |
|
462
|
|
|
} catch (Exception $e) { |
|
463
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP2</strong> found but not working properly, perhaps you need to download the databases. See utils/GeoIP-update.sh in the CAT distribution and use it to update the GeoIP database regularly."); |
|
464
|
|
|
return; |
|
465
|
|
|
} |
|
466
|
|
|
if ($record->city->name != 'Utrecht') { |
|
467
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP2</strong> found but not working properly, perhaps you need to download the databases. See utils/GeoIP-update.sh in the CAT distribution and use it to update the GeoIP database regularly."); |
|
468
|
|
|
return; |
|
469
|
|
|
} |
|
470
|
|
|
try { |
|
471
|
|
|
$record = $reader->city($host_6); |
|
472
|
|
|
} catch (Exception $e) { |
|
473
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP2</strong> found but not working properly with IPv6, perhaps you need to download the databases. See utils/GeoIP-update.sh in the CAT distribution and use it tu update the GeoIP database regularly."); |
|
474
|
|
|
return; |
|
475
|
|
|
} |
|
476
|
|
|
if ($record->city->name != 'Utrecht') { |
|
477
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "PHP extension <strong>GeoIP2</strong> found but not working properly with IPv6, perhaps you need to download the databases. See utils/GeoIP-update.sh in the CAT distribution and use it tu update the GeoIP database regularly."); |
|
478
|
|
|
return; |
|
479
|
|
|
} |
|
480
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "PHP extension <strong>GeoIP2</strong> is installed and working. See utils/GeoIP-update.sh in the CAT distribution and use it tu update the GeoIP database regularly."); |
|
481
|
|
|
break; |
|
482
|
|
|
default: |
|
483
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, 'Check CONFIG[\'GEOIP\'][\'version\'], it must be set to either 1 or 2'); |
|
484
|
|
|
break; |
|
485
|
|
|
} |
|
486
|
|
|
} |
|
487
|
|
|
|
|
488
|
|
|
/** |
|
489
|
|
|
* test if openssl is available |
|
490
|
|
|
* |
|
491
|
|
|
* @return void |
|
492
|
|
|
*/ |
|
493
|
|
|
private function testOpenssl() { |
|
494
|
|
|
$A = $this->getExecPath('openssl'); |
|
495
|
|
|
if ($A['exec'] != "") { |
|
496
|
|
|
$t = exec($A['exec'] . ' version'); |
|
497
|
|
|
if ($A['exec_is'] == "EXPLICIT") { |
|
498
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "<strong>$t</strong> was found and is configured explicitly in your config."); |
|
499
|
|
|
} else { |
|
500
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "<strong>$t</strong> was found, but is not configured with an absolute path in your config."); |
|
501
|
|
|
} |
|
502
|
|
|
} else { |
|
503
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>openssl</strong> was not found on your system!"); |
|
504
|
|
|
} |
|
505
|
|
|
} |
|
506
|
|
|
|
|
507
|
|
|
/** |
|
508
|
|
|
* test if makensis is available |
|
509
|
|
|
* |
|
510
|
|
|
* @return void |
|
511
|
|
|
*/ |
|
512
|
|
|
private function testMakensis() { |
|
513
|
|
|
if (!is_numeric(CONFIG_CONFASSISTANT['NSIS_VERSION'])) { |
|
514
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "NSIS_VERSION needs to be numeric!"); |
|
515
|
|
|
return; |
|
516
|
|
|
} |
|
517
|
|
|
if (CONFIG_CONFASSISTANT['NSIS_VERSION'] < 2) { |
|
518
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "NSIS_VERSION needs to be at least 2!"); |
|
519
|
|
|
return; |
|
520
|
|
|
} |
|
521
|
|
|
$A = $this->getExecPath('makensis'); |
|
522
|
|
|
if ($A['exec'] != "") { |
|
523
|
|
|
$t = exec($A['exec'] . ' -VERSION'); |
|
524
|
|
|
if ($A['exec_is'] == "EXPLICIT") { |
|
525
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "<strong>makensis $t</strong> was found and is configured explicitly in your config."); |
|
526
|
|
|
} else { |
|
527
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "<strong>makensis $t</strong> was found, but is not configured with an absolute path in your config."); |
|
528
|
|
|
} |
|
529
|
|
|
$outputArray = []; |
|
530
|
|
|
exec($A['exec'] . ' -HELP', $outputArray); |
|
531
|
|
|
$t1 = count(preg_grep('/INPUTCHARSET/', $outputArray)); |
|
532
|
|
|
if ($t1 == 1 && CONFIG_CONFASSISTANT['NSIS_VERSION'] == 2) { |
|
533
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Declared NSIS_VERSION does not seem to match the file pointed to by PATHS['makensis']!"); |
|
534
|
|
|
} |
|
535
|
|
|
if ($t1 == 0 && CONFIG_CONFASSISTANT['NSIS_VERSION'] >= 3) { |
|
536
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Declared NSIS_VERSION does not seem to match the file pointed to by PATHS['makensis']!"); |
|
537
|
|
|
} |
|
538
|
|
|
} else { |
|
539
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "<strong>makensis</strong> was not found on your system!"); |
|
540
|
|
|
} |
|
541
|
|
|
} |
|
542
|
|
|
|
|
543
|
|
|
/** |
|
544
|
|
|
* test if all required NSIS modules are available |
|
545
|
|
|
* |
|
546
|
|
|
* @return void |
|
547
|
|
|
*/ |
|
548
|
|
|
private function testNSISmodules() { |
|
549
|
|
|
$tmp_dir = \core\common\Entity::createTemporaryDirectory('installer', 0)['dir']; |
|
550
|
|
|
if (!chdir($tmp_dir)) { |
|
551
|
|
|
$this->loggerInstance->debug(2, "Cannot chdir to $tmp_dir\n"); |
|
552
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "NSIS modules test - problem with temporary directory permissions, cannot continue"); |
|
553
|
|
|
return; |
|
554
|
|
|
} |
|
555
|
|
|
$exe = 'tt.exe'; |
|
556
|
|
|
$NSIS_Module_status = []; |
|
557
|
|
|
foreach ($this->NSIS_Modules as $module) { |
|
558
|
|
|
unset($out); |
|
559
|
|
|
exec(CONFIG_CONFASSISTANT['PATHS']['makensis'] . " -V1 '-X!include $module' '-XOutFile $exe' '-XSection X' '-XSectionEnd'", $out, $retval); |
|
560
|
|
|
if ($retval > 0) { |
|
561
|
|
|
$NSIS_Module_status[$module] = 0; |
|
562
|
|
|
} else { |
|
563
|
|
|
$NSIS_Module_status[$module] = 1; |
|
564
|
|
|
} |
|
565
|
|
|
} |
|
566
|
|
|
if (is_file($exe)) { |
|
567
|
|
|
unlink($exe); |
|
568
|
|
|
} |
|
569
|
|
|
foreach ($NSIS_Module_status as $module => $status) { |
|
570
|
|
|
if ($status == 1) { |
|
571
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "NSIS module <strong>$module</strong> was found."); |
|
572
|
|
|
} else { |
|
573
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "NSIS module <strong>$module</strong> was not found or is not working correctly."); |
|
574
|
|
|
} |
|
575
|
|
|
} |
|
576
|
|
|
} |
|
577
|
|
|
|
|
578
|
|
|
/** |
|
579
|
|
|
* test access to dowloads directories |
|
580
|
|
|
* |
|
581
|
|
|
* @return void |
|
582
|
|
|
*/ |
|
583
|
|
|
private function testDirectories() { |
|
584
|
|
|
$Dir1 = \core\common\Entity::createTemporaryDirectory('installer', 0); |
|
585
|
|
|
$dir1 = $Dir1['dir']; |
|
586
|
|
|
$base1 = $Dir1['base']; |
|
587
|
|
|
if ($dir1) { |
|
588
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "Installer cache directory is writable."); |
|
589
|
|
|
\core\common\Entity::rrmdir($dir1); |
|
590
|
|
|
} else { |
|
591
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Installer cache directory $base1 does not exist or is not writable!"); |
|
592
|
|
|
} |
|
593
|
|
|
$Dir2 = \core\common\Entity::createTemporaryDirectory('test', 0); |
|
594
|
|
|
$dir2 = $Dir2['dir']; |
|
595
|
|
|
$base2 = $Dir2['base']; |
|
596
|
|
|
if ($dir2) { |
|
597
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "Test directory is writable."); |
|
598
|
|
|
\core\common\Entity::rrmdir($dir2); |
|
599
|
|
|
} else { |
|
600
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Test directory $base2 does not exist or is not writable!"); |
|
601
|
|
|
} |
|
602
|
|
|
$Dir3 = \core\common\Entity::createTemporaryDirectory('logo', 0); |
|
603
|
|
|
$dir3 = $Dir3['dir']; |
|
604
|
|
|
$base3 = $Dir3['base']; |
|
605
|
|
|
if ($dir3) { |
|
606
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "Logos cache directory is writable."); |
|
607
|
|
|
\core\common\Entity::rrmdir($dir3); |
|
608
|
|
|
} else { |
|
609
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Logos cache directory $base3 does not exist or is not writable!"); |
|
610
|
|
|
} |
|
611
|
|
|
} |
|
612
|
|
|
|
|
613
|
|
|
/** |
|
614
|
|
|
* test if all required locales are enabled |
|
615
|
|
|
* |
|
616
|
|
|
* @return void |
|
617
|
|
|
*/ |
|
618
|
|
|
private function testLocales() { |
|
619
|
|
|
$locales = shell_exec("locale -a"); |
|
620
|
|
|
$allthere = ""; |
|
621
|
|
|
foreach (CONFIG['LANGUAGES'] as $onelanguage) { |
|
622
|
|
|
if (preg_match("/" . $onelanguage['locale'] . "/", $locales) == 0) { |
|
623
|
|
|
$allthere .= $onelanguage['locale'] . " "; |
|
624
|
|
|
} |
|
625
|
|
|
} |
|
626
|
|
|
if ($allthere == "") { |
|
627
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "All of your configured locales are available on your system."); |
|
628
|
|
|
} else { |
|
629
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "Some of your configured locales (<strong>$allthere</strong>) are not installed and will not be displayed correctly!"); |
|
630
|
|
|
} |
|
631
|
|
|
} |
|
632
|
|
|
|
|
633
|
|
|
const DEFAULTS = [ |
|
634
|
|
|
["SETTING" => CONFIG['APPEARANCE']['from-mail'], |
|
635
|
|
|
"DEFVALUE" => "[email protected]", |
|
636
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/from-mail ", |
|
637
|
|
|
"REQUIRED" => FALSE,], |
|
638
|
|
|
["SETTING" => CONFIG['APPEARANCE']['support-contact']['url'], |
|
639
|
|
|
"DEFVALUE" => "[email protected]?body=Only%20English%20language%20please!", |
|
640
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/support-contact/url ", |
|
641
|
|
|
"REQUIRED" => FALSE,], |
|
642
|
|
|
["SETTING" => CONFIG['APPEARANCE']['support-contact']['display'], |
|
643
|
|
|
"DEFVALUE" => "[email protected]", |
|
644
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/support-contact/display ", |
|
645
|
|
|
"REQUIRED" => FALSE,], |
|
646
|
|
|
["SETTING" => CONFIG['APPEARANCE']['support-contact']['developer-mail'], |
|
647
|
|
|
"DEFVALUE" => "[email protected]", |
|
648
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/support-contact/mail ", |
|
649
|
|
|
"REQUIRED" => FALSE,], |
|
650
|
|
|
["SETTING" => CONFIG['APPEARANCE']['abuse-mail'], |
|
651
|
|
|
"DEFVALUE" => "[email protected]", |
|
652
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/abuse-mail ", |
|
653
|
|
|
"REQUIRED" => FALSE,], |
|
654
|
|
|
["SETTING" => CONFIG['APPEARANCE']['MOTD'], |
|
655
|
|
|
"DEFVALUE" => "Release Candidate. All bugs to be shot on sight!", |
|
656
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/MOTD ", |
|
657
|
|
|
"REQUIRED" => FALSE,], |
|
658
|
|
|
["SETTING" => CONFIG['APPEARANCE']['webcert_CRLDP'], |
|
659
|
|
|
"DEFVALUE" => ['list', 'of', 'CRL', 'pointers'], |
|
660
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/webcert_CRLDP ", |
|
661
|
|
|
"REQUIRED" => TRUE,], |
|
662
|
|
|
["SETTING" => CONFIG['APPEARANCE']['webcert_OCSP'], |
|
663
|
|
|
"DEFVALUE" => ['list', 'of', 'OCSP', 'pointers'], |
|
664
|
|
|
"COMPLAINTSTRING" => "APPEARANCE/webcert_OCSP ", |
|
665
|
|
|
"REQUIRED" => TRUE,], |
|
666
|
|
|
["SETTING" => CONFIG['DB']['INST']['host'], |
|
667
|
|
|
"DEFVALUE" => "db.host.example", |
|
668
|
|
|
"COMPLAINTSTRING" => "DB/INST ", |
|
669
|
|
|
"REQUIRED" => TRUE,], |
|
670
|
|
|
["SETTING" => CONFIG['DB']['INST']['host'], |
|
671
|
|
|
"DEFVALUE" => "db.host.example", |
|
672
|
|
|
"COMPLAINTSTRING" => "DB/USER ", |
|
673
|
|
|
"REQUIRED" => TRUE,], |
|
674
|
|
|
["SETTING" => CONFIG['DB']['EXTERNAL']['host'], |
|
675
|
|
|
"DEFVALUE" => "customerdb.otherhost.example", |
|
676
|
|
|
"COMPLAINTSTRING" => "DB/EXTERNAL ", |
|
677
|
|
|
"REQUIRED" => FALSE,], |
|
678
|
|
|
]; |
|
679
|
|
|
|
|
680
|
|
|
/** |
|
681
|
|
|
* test if defaults in the config have been replaced with some real values |
|
682
|
|
|
* |
|
683
|
|
|
* @return void |
|
684
|
|
|
*/ |
|
685
|
|
|
private function testDefaults() { |
|
686
|
|
|
$defaultvalues = ""; |
|
687
|
|
|
$missingvalues = ""; |
|
688
|
|
|
// all the checks for equality with a shipped default value |
|
689
|
|
|
foreach (SanityTests::DEFAULTS as $oneCheckItem) { |
|
690
|
|
|
if ($oneCheckItem['REQUIRED'] && !$oneCheckItem['SETTING']) { |
|
691
|
|
|
$missingvalues .= $oneCheckItem["COMPLAINTSTRING"]; |
|
692
|
|
|
} elseif ($oneCheckItem['SETTING'] == $oneCheckItem["DEFVALUE"]) { |
|
693
|
|
|
$defaultvalues .= $oneCheckItem["COMPLAINTSTRING"]; |
|
694
|
|
|
} |
|
695
|
|
|
} |
|
696
|
|
|
// additional checks for defaults, which are not simple equality checks |
|
697
|
|
|
if (isset(CONFIG_DIAGNOSTICS['RADIUSTESTS']['UDP-hosts'][0]) && CONFIG_DIAGNOSTICS['RADIUSTESTS']['UDP-hosts'][0]['ip'] == "192.0.2.1") { |
|
698
|
|
|
$defaultvalues .= "RADIUSTESTS/UDP-hosts "; |
|
699
|
|
|
} |
|
700
|
|
|
|
|
701
|
|
|
foreach (CONFIG_DIAGNOSTICS['RADIUSTESTS']['TLS-clientcerts'] as $cadata) { |
|
702
|
|
|
foreach ($cadata['certificates'] as $cert_files) { |
|
703
|
|
|
if (file_get_contents(ROOT . "/config/cli-certs/" . $cert_files['public']) === FALSE) { |
|
704
|
|
|
$defaultvalues .= "CERTIFICATE/" . $cert_files['public'] . " "; |
|
705
|
|
|
} |
|
706
|
|
|
if (file_get_contents(ROOT . "/config/cli-certs/" . $cert_files['private']) === FALSE) { |
|
707
|
|
|
$defaultvalues .= "CERTIFICATE/" . $cert_files['private'] . " "; |
|
708
|
|
|
} |
|
709
|
|
|
} |
|
710
|
|
|
} |
|
711
|
|
|
|
|
712
|
|
|
if ($defaultvalues != "") { |
|
713
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "Your configuration in config/config.php contains unchanged default values or links to inexistent files: <strong>$defaultvalues</strong>!"); |
|
714
|
|
|
} else { |
|
715
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "Your configuration does not contain any unchanged defaults, which is a good sign."); |
|
716
|
|
|
} |
|
717
|
|
|
} |
|
718
|
|
|
|
|
719
|
|
|
/** |
|
720
|
|
|
* test access to databases |
|
721
|
|
|
* |
|
722
|
|
|
* @return void |
|
723
|
|
|
*/ |
|
724
|
|
|
private function testDatabases() { |
|
725
|
|
|
$databaseName1 = 'INST'; |
|
726
|
|
|
try { |
|
727
|
|
|
$db1 = DBConnection::handle($databaseName1); |
|
728
|
|
|
$res1 = $db1->exec('SELECT * FROM profile_option_dict'); |
|
729
|
|
|
if ($res1->num_rows == $this->profile_option_ct) { |
|
730
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "The $databaseName1 database appears to be OK."); |
|
731
|
|
|
} else { |
|
732
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "The $databaseName1 database is reacheable but probably not updated to this version of CAT."); |
|
733
|
|
|
} |
|
734
|
|
|
} catch (Exception $e) { |
|
735
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Connection to the $databaseName1 database failed"); |
|
736
|
|
|
} |
|
737
|
|
|
|
|
738
|
|
|
$databaseName2 = 'USER'; |
|
739
|
|
|
try { |
|
740
|
|
|
$db2 = DBConnection::handle($databaseName2); |
|
741
|
|
|
if (CONFIG_CONFASSISTANT['CONSORTIUM']['name'] == "eduroam" && isset(CONFIG_CONFASSISTANT['CONSORTIUM']['deployment-voodoo']) && CONFIG_CONFASSISTANT['CONSORTIUM']['deployment-voodoo'] == "Operations Team") { // SW: APPROVED |
|
742
|
|
|
$res2 = $db2->exec('desc view_admin'); |
|
743
|
|
|
if ($res2->num_rows == $this->view_admin_ct) { |
|
744
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "The $databaseName2 database appears to be OK."); |
|
745
|
|
|
} else { |
|
746
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "The $databaseName2 is reacheable but there is something wrong with the schema"); |
|
747
|
|
|
} |
|
748
|
|
|
} else { |
|
749
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "The $databaseName2 database appears to be OK."); |
|
750
|
|
|
} |
|
751
|
|
|
} catch (Exception $e) { |
|
752
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Connection to the $databaseName2 database failed"); |
|
753
|
|
|
} |
|
754
|
|
|
|
|
755
|
|
|
$databaseName3 = 'EXTERNAL'; |
|
756
|
|
|
if (!empty(CONFIG['DB'][$databaseName3])) { |
|
757
|
|
|
try { |
|
758
|
|
|
$db3 = DBConnection::handle($databaseName3); |
|
759
|
|
|
if (CONFIG_CONFASSISTANT['CONSORTIUM']['name'] == "eduroam" && isset(CONFIG_CONFASSISTANT['CONSORTIUM']['deployment-voodoo']) && CONFIG_CONFASSISTANT['CONSORTIUM']['deployment-voodoo'] == "Operations Team") { // SW: APPROVED |
|
760
|
|
|
$res3 = $db3->exec('desc view_admin'); |
|
761
|
|
|
if ($res3->num_rows == $this->view_admin_ct) { |
|
762
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "The $databaseName3 database appears to be OK."); |
|
763
|
|
|
} else { |
|
764
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "The $databaseName3 is reacheable but there is something wrong with the schema"); |
|
765
|
|
|
} |
|
766
|
|
|
} else { |
|
767
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "The $databaseName3 database appears to be OK."); |
|
768
|
|
|
} |
|
769
|
|
|
} catch (Exception $e) { |
|
770
|
|
|
|
|
771
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Connection to the $databaseName3 database failed"); |
|
772
|
|
|
} |
|
773
|
|
|
} |
|
774
|
|
|
} |
|
775
|
|
|
|
|
776
|
|
|
/** |
|
777
|
|
|
* test devices.php for the no_cache option |
|
778
|
|
|
* |
|
779
|
|
|
* @return void |
|
780
|
|
|
*/ |
|
781
|
|
|
private function testDeviceCache() { |
|
782
|
|
|
if ((!empty(\devices\Devices::$Options['no_cache'])) && \devices\Devices::$Options['no_cache']) { |
|
783
|
|
|
$global_no_cache = 1; |
|
784
|
|
|
} else { |
|
785
|
|
|
$global_no_cache = 0; |
|
786
|
|
|
} |
|
787
|
|
|
|
|
788
|
|
|
if ($global_no_cache == 1) { |
|
789
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "Devices no_cache global option is set, this is not a good idea in a production setting\n"); |
|
790
|
|
|
} |
|
791
|
|
|
$Devs = \devices\Devices::listDevices(); |
|
792
|
|
|
$no_cache_dev = ''; |
|
793
|
|
|
$no_cache_dev_count = 0; |
|
794
|
|
|
if ($global_no_cache) { |
|
795
|
|
|
foreach ($Devs as $dev => $D) { |
|
796
|
|
|
if (empty($D['options']['no_cache']) || $D['options']['no_cache'] != 0) { |
|
797
|
|
|
$no_cache_dev .= $dev . " "; |
|
798
|
|
|
$no_cache_dev_count++; |
|
799
|
|
|
} |
|
800
|
|
|
} |
|
801
|
|
|
} else { |
|
802
|
|
|
foreach ($Devs as $dev => $D) { |
|
803
|
|
|
if (!empty($D['options']['no_cache']) && $D['options']['no_cache'] != 0) { |
|
804
|
|
|
$no_cache_dev .= $dev . " "; |
|
805
|
|
|
$no_cache_dev_count++; |
|
806
|
|
|
} |
|
807
|
|
|
} |
|
808
|
|
|
} |
|
809
|
|
|
|
|
810
|
|
|
|
|
811
|
|
|
if ($no_cache_dev_count > 1) { |
|
812
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "The following devices will not be cached: $no_cache_dev"); |
|
813
|
|
|
} |
|
814
|
|
|
if ($no_cache_dev_count == 1) { |
|
815
|
|
|
$this->storeTestResult(\core\common\Entity::L_WARN, "The following device will not be cached: $no_cache_dev"); |
|
816
|
|
|
} |
|
817
|
|
|
} |
|
818
|
|
|
|
|
819
|
|
|
/** |
|
820
|
|
|
* test if mailer works |
|
821
|
|
|
* |
|
822
|
|
|
* @return void |
|
823
|
|
|
*/ |
|
824
|
|
|
private function testMailer() { |
|
825
|
|
|
if (empty(CONFIG['APPEARANCE']['abuse-mail']) || CONFIG['APPEARANCE']['abuse-mail'] == "[email protected]") { |
|
826
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "Your abuse-mail has not been set, cannot continue with mailer tests."); |
|
827
|
|
|
return; |
|
828
|
|
|
} |
|
829
|
|
|
$mail = new \PHPMailer\PHPMailer\PHPMailer(); |
|
830
|
|
|
$mail->isSMTP(); |
|
831
|
|
|
$mail->Port = 587; |
|
832
|
|
|
$mail->SMTPAuth = true; |
|
833
|
|
|
$mail->SMTPSecure = 'tls'; |
|
834
|
|
|
$mail->Host = CONFIG['MAILSETTINGS']['host']; |
|
835
|
|
|
$mail->Username = CONFIG['MAILSETTINGS']['user']; |
|
836
|
|
|
$mail->Password = CONFIG['MAILSETTINGS']['pass']; |
|
837
|
|
|
$mail->SMTPOptions = CONFIG['MAILSETTINGS']['options']; |
|
838
|
|
|
$mail->WordWrap = 72; |
|
839
|
|
|
$mail->isHTML(FALSE); |
|
840
|
|
|
$mail->CharSet = 'UTF-8'; |
|
841
|
|
|
$mail->From = CONFIG['APPEARANCE']['from-mail']; |
|
842
|
|
|
$mail->FromName = CONFIG['APPEARANCE']['productname'] . " Invitation System"; |
|
843
|
|
|
$mail->addAddress(CONFIG['APPEARANCE']['abuse-mail']); |
|
844
|
|
|
$mail->Subject = "testing CAT configuration mail"; |
|
845
|
|
|
$mail->Body = "Testing CAT mailing\n"; |
|
846
|
|
|
$sent = $mail->send(); |
|
847
|
|
|
if ($sent) { |
|
848
|
|
|
$this->storeTestResult(\core\common\Entity::L_OK, "mailer settings appear to be working, check " . CONFIG['APPEARANCE']['abuse-mail'] . " mailbox if the message was receiced."); |
|
849
|
|
|
} else { |
|
850
|
|
|
$this->storeTestResult(\core\common\Entity::L_ERROR, "mailer settings failed, check the Config::MAILSETTINGS"); |
|
851
|
|
|
} |
|
852
|
|
|
} |
|
853
|
|
|
} |
|
854
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.