UPDATE 4.4.0.0
[phpmyadmin.git] / libraries / config / ServerConfigChecks.class.php
blob531579708372295a580f72702e5e347f4878710b
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Server config checks management
6 * @package PhpMyAdmin
7 */
9 /**
10 * Performs various compatibility, security and consistency checks on current config
12 * Outputs results to message list, must be called between PMA_messagesBegin()
13 * and PMA_messagesEnd()
15 * @package PhpMyAdmin
17 class ServerConfigChecks
19 /**
20 * @var ConfigFile configurations being checked
22 protected $cfg;
24 /**
25 * Constructor.
27 * @param ConfigFile $cfg Configuration
29 public function __construct(ConfigFile $cfg)
31 $this->cfg = $cfg;
34 /**
35 * Perform config checks
37 * @return void
39 public function performConfigChecks()
41 $blowfishSecret = $this->cfg->get('blowfish_secret');
42 $blowfishSecretSet = false;
43 $cookieAuthUsed = false;
45 list(
46 $sAllowArbitraryServerWarn, $sBlowfishSecretMsg,
47 $sBZipDumpWarn, $sDirectoryNotice, $sForceSSLNotice,
48 $sGZipDumpWarn, $sLoginCookieValidityWarn,
49 $sLoginCookieValidityWarn2, $sLoginCookieValidityWarn3,
50 $sSecurityInfoMsg, $sSrvAuthCfgMsg, $sZipDumpExportWarn,
51 $sZipDumpImportWarn
52 ) = self::defineMessages();
54 list($cookieAuthUsed, $blowfishSecret, $blowfishSecretSet)
55 = $this->performConfigChecksServers(
56 $cookieAuthUsed, $blowfishSecret, $sSrvAuthCfgMsg,
57 $sSecurityInfoMsg, $blowfishSecretSet
60 $this->performConfigChecksCookieAuthUsed(
61 $cookieAuthUsed, $blowfishSecretSet, $sBlowfishSecretMsg,
62 $blowfishSecret
66 // $cfg['ForceSSL']
67 // should be enabled if possible
69 if (!$this->cfg->getValue('ForceSSL')) {
70 PMA_messagesSet(
71 'notice',
72 'ForceSSL',
73 PMA_lang(PMA_langName('ForceSSL')),
74 PMA_lang($sForceSSLNotice)
79 // $cfg['AllowArbitraryServer']
80 // should be disabled
82 if ($this->cfg->getValue('AllowArbitraryServer')) {
83 PMA_messagesSet(
84 'notice',
85 'AllowArbitraryServer',
86 PMA_lang(PMA_langName('AllowArbitraryServer')),
87 PMA_lang($sAllowArbitraryServerWarn)
91 $this->performConfigChecksLoginCookie(
92 $sLoginCookieValidityWarn, $sLoginCookieValidityWarn2,
93 $sLoginCookieValidityWarn3
97 // $cfg['SaveDir']
98 // should not be world-accessible
100 if ($this->cfg->getValue('SaveDir') != '') {
101 PMA_messagesSet(
102 'notice',
103 'SaveDir',
104 PMA_lang(PMA_langName('SaveDir')),
105 PMA_lang($sDirectoryNotice)
110 // $cfg['TempDir']
111 // should not be world-accessible
113 if ($this->cfg->getValue('TempDir') != '') {
114 PMA_messagesSet(
115 'notice',
116 'TempDir',
117 PMA_lang(PMA_langName('TempDir')),
118 PMA_lang($sDirectoryNotice)
122 $this->performConfigChecksZips(
123 $sGZipDumpWarn, $sBZipDumpWarn, $sZipDumpImportWarn,
124 $sZipDumpExportWarn
129 * Check config of servers
131 * @param boolean $cookieAuthUsed Cookie auth is used
132 * @param string $blowfishSecret Blowfish secret
133 * @param string $sServerAuthCfgMsg Message for server auth config
134 * @param string $sSecurityInfoMsg Message for security information
135 * @param boolean $blowfishSecretSet Blowfish secret set
137 * @return array
139 protected function performConfigChecksServers(
140 $cookieAuthUsed, $blowfishSecret, $sServerAuthCfgMsg,
141 $sSecurityInfoMsg, $blowfishSecretSet
143 $serverCnt = $this->cfg->getServerCount();
144 for ($i = 1; $i <= $serverCnt; $i++) {
145 $cookieAuthServer
146 = ($this->cfg->getValue("Servers/$i/auth_type") == 'cookie');
147 $cookieAuthUsed |= $cookieAuthServer;
148 $serverName = $this->performConfigChecksServersGetServerName(
149 $this->cfg->getServerName($i), $i
151 $serverName = htmlspecialchars($serverName);
153 list($blowfishSecret, $blowfishSecretSet)
154 = $this->performConfigChecksServersSetBlowfishSecret(
155 $blowfishSecret, $cookieAuthServer, $blowfishSecretSet
159 // $cfg['Servers'][$i]['ssl']
160 // should be enabled if possible
162 if (!$this->cfg->getValue("Servers/$i/ssl")) {
163 $title = PMA_lang(PMA_langName('Servers/1/ssl')) . " ($serverName)";
164 PMA_messagesSet(
165 'notice',
166 "Servers/$i/ssl",
167 $title,
168 __('You should use SSL connections if your database server supports it.')
173 // $cfg['Servers'][$i]['auth_type']
174 // warn about full user credentials if 'auth_type' is 'config'
176 if ($this->cfg->getValue("Servers/$i/auth_type") == 'config'
177 && $this->cfg->getValue("Servers/$i/user") != ''
178 && $this->cfg->getValue("Servers/$i/password") != ''
180 $title = PMA_lang(PMA_langName('Servers/1/auth_type'))
181 . " ($serverName)";
182 PMA_messagesSet(
183 'notice',
184 "Servers/$i/auth_type",
185 $title,
186 PMA_lang($sServerAuthCfgMsg, $i) . ' '
187 . PMA_lang($sSecurityInfoMsg, $i)
192 // $cfg['Servers'][$i]['AllowRoot']
193 // $cfg['Servers'][$i]['AllowNoPassword']
194 // serious security flaw
196 if ($this->cfg->getValue("Servers/$i/AllowRoot")
197 && $this->cfg->getValue("Servers/$i/AllowNoPassword")
199 $title = PMA_lang(PMA_langName('Servers/1/AllowNoPassword'))
200 . " ($serverName)";
201 PMA_messagesSet(
202 'notice',
203 "Servers/$i/AllowNoPassword",
204 $title,
205 __('You allow for connecting to the server without a password.') . ' '
206 . PMA_lang($sSecurityInfoMsg, $i)
210 return array($cookieAuthUsed, $blowfishSecret, $blowfishSecretSet);
214 * Set blowfish secret
216 * @param string $blowfishSecret Blowfish secret
217 * @param boolean $cookieAuthServer Cookie auth is used
218 * @param boolean $blowfishSecretSet Blowfish secret set
220 * @return array
222 protected function performConfigChecksServersSetBlowfishSecret(
223 $blowfishSecret, $cookieAuthServer, $blowfishSecretSet
225 if ($cookieAuthServer && $blowfishSecret === null) {
226 $blowfishSecret = uniqid('', true);
227 $blowfishSecretSet = true;
228 $this->cfg->set('blowfish_secret', $blowfishSecret);
229 return array($blowfishSecret, $blowfishSecretSet);
231 return array($blowfishSecret, $blowfishSecretSet);
235 * Define server name
237 * @param string $serverName Server name
238 * @param int $serverId Server id
240 * @return string Server name
242 protected function performConfigChecksServersGetServerName(
243 $serverName, $serverId
245 if ($serverName == 'localhost') {
246 $serverName .= " [$serverId]";
247 return $serverName;
249 return $serverName;
253 * Perform config checks for zip part.
255 * @param string $sGZipDumpWarning Gzip dump warning
256 * @param string $sBZipDumpWarning Bzip dump warning
257 * @param string $sZipDumpImportWarn Zip dump import warning
258 * @param string $sZipDumpExportWarn Zip dump export warning
260 * @return void
262 protected function performConfigChecksZips(
263 $sGZipDumpWarning, $sBZipDumpWarning, $sZipDumpImportWarn,
264 $sZipDumpExportWarn
266 $this->performConfigChecksServerGZipdump($sGZipDumpWarning);
267 $this->performConfigChecksServerBZipdump($sBZipDumpWarning);
268 $this->performConfigChecksServersZipdump(
269 $sZipDumpImportWarn, $sZipDumpExportWarn
274 * Perform config checks for zip part.
276 * @param string $sZipDumpImportWarn Zip dump import warning
277 * @param string $sZipDumpExportWarn Zip dump export warning
279 * @return void
281 protected function performConfigChecksServersZipdump(
282 $sZipDumpImportWarn, $sZipDumpExportWarn
285 // $cfg['ZipDump']
286 // requires zip_open in import
288 if ($this->cfg->getValue('ZipDump') && !@function_exists('zip_open')) {
289 PMA_messagesSet(
290 'error',
291 'ZipDump_import',
292 PMA_lang(PMA_langName('ZipDump')),
293 PMA_lang($sZipDumpImportWarn, 'zip_open')
298 // $cfg['ZipDump']
299 // requires gzcompress in export
301 if ($this->cfg->getValue('ZipDump') && !@function_exists('gzcompress')) {
302 PMA_messagesSet(
303 'error',
304 'ZipDump_export',
305 PMA_lang(PMA_langName('ZipDump')),
306 PMA_lang($sZipDumpExportWarn, 'gzcompress')
312 * Check config of servers
314 * @param boolean $cookieAuthUsed Cookie auth is used
315 * @param boolean $blowfishSecretSet Blowfish secret set
316 * @param string $sBlowfishSecretMsg Blowfish secret message
317 * @param string $blowfishSecret Blowfish secret
319 * @return array
321 protected function performConfigChecksCookieAuthUsed(
322 $cookieAuthUsed, $blowfishSecretSet, $sBlowfishSecretMsg,
323 $blowfishSecret
326 // $cfg['blowfish_secret']
327 // it's required for 'cookie' authentication
329 if ($cookieAuthUsed) {
330 if ($blowfishSecretSet) {
331 // 'cookie' auth used, blowfish_secret was generated
332 PMA_messagesSet(
333 'notice',
334 'blowfish_secret_created',
335 PMA_lang(PMA_langName('blowfish_secret')),
336 PMA_lang($sBlowfishSecretMsg)
338 } else {
339 $blowfishWarnings = array();
340 // check length
341 if (/*overload*/mb_strlen($blowfishSecret) < 8) {
342 // too short key
343 $blowfishWarnings[] = __('Key is too short, it should have at least 8 characters.');
345 // check used characters
346 $hasDigits = (bool)preg_match('/\d/', $blowfishSecret);
347 $hasChars = (bool)preg_match('/\S/', $blowfishSecret);
348 $hasNonword = (bool)preg_match('/\W/', $blowfishSecret);
349 if (!$hasDigits || !$hasChars || !$hasNonword) {
350 $blowfishWarnings[] = PMA_lang(__('Key should contain letters, numbers [em]and[/em] special characters.'));
352 if (!empty($blowfishWarnings)) {
353 PMA_messagesSet(
354 'error',
355 'blowfish_warnings' . count($blowfishWarnings),
356 PMA_lang(PMA_langName('blowfish_secret')),
357 implode('<br />', $blowfishWarnings)
365 * Define all messages
367 * @return array
369 protected static function defineMessages()
371 $sAllowArbitraryServerWarn = __('This %soption%s should be disabled as it allows attackers to bruteforce login to any MySQL server. If you feel this is necessary, use %srestrict login to MySQL server%s or %strusted proxies list%s. However, IP-based protection with trusted proxies list may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
372 $sAllowArbitraryServerWarn = sprintf(
373 $sAllowArbitraryServerWarn,
374 '[a@?page=form&amp;formset=Features#tab_Security]',
375 '[/a]',
376 '[a@?page=form&amp;formset=Features#tab_Security]',
377 '[/a]',
378 '[a@?page=form&amp;formset=Features#tab_Security]',
379 '[/a]'
381 $sBlowfishSecretMsg = __('You didn\'t have blowfish secret set and have enabled [kbd]cookie[/kbd] authentication, so a key was automatically generated for you. It is used to encrypt cookies; you don\'t need to remember it.');
382 $sBZipDumpWarning = __('%sBzip2 compression and decompression%s requires functions (%s) which are unavailable on this system.');
383 $sBZipDumpWarning = sprintf(
384 $sBZipDumpWarning,
385 '[a@?page=form&amp;formset=Features#tab_Import_export]',
386 '[/a]', '%s'
388 $sDirectoryNotice = __('This value should be double checked to ensure that this directory is neither world accessible nor readable or writable by other users on your server.');
389 $sForceSSLNotice = __('This %soption%s should be enabled if your web server supports it.');
390 $sForceSSLNotice = sprintf(
391 $sForceSSLNotice,
392 '[a@?page=form&amp;formset=Features#tab_Security]',
393 '[/a]'
395 $sGZipDumpWarning = __('%sGZip compression and decompression%s requires functions (%s) which are unavailable on this system.');
396 $sGZipDumpWarning = sprintf(
397 $sGZipDumpWarning,
398 '[a@?page=form&amp;formset=Features#tab_Import_export]',
399 '[/a]',
400 '%s'
402 $sLoginCookieValidityWarn = __('%sLogin cookie validity%s greater than %ssession.gc_maxlifetime%s may cause random session invalidation (currently session.gc_maxlifetime is %d).');
403 $sLoginCookieValidityWarn = sprintf(
404 $sLoginCookieValidityWarn,
405 '[a@?page=form&amp;formset=Features#tab_Security]',
406 '[/a]',
407 '[a@' . PMA_getPHPDocLink(
408 'session.configuration.php#ini.session.gc-maxlifetime'
409 ) . ']',
410 '[/a]',
411 ini_get('session.gc_maxlifetime')
413 $sLoginCookieValidityWarn2 = __('%sLogin cookie validity%s should be set to 1800 seconds (30 minutes) at most. Values larger than 1800 may pose a security risk such as impersonation.');
414 $sLoginCookieValidityWarn2 = sprintf(
415 $sLoginCookieValidityWarn2,
416 '[a@?page=form&amp;formset=Features#tab_Security]',
417 '[/a]'
419 $sLoginCookieValidityWarn3 = __('If using [kbd]cookie[/kbd] authentication and %sLogin cookie store%s is not 0, %sLogin cookie validity%s must be set to a value less or equal to it.');
420 $sLoginCookieValidityWarn3 = sprintf(
421 $sLoginCookieValidityWarn3,
422 '[a@?page=form&amp;formset=Features#tab_Security]',
423 '[/a]', '[a@?page=form&amp;formset=Features#tab_Security]',
424 '[/a]'
426 $sSecurityInfoMsg = __('If you feel this is necessary, use additional protection settings - %shost authentication%s settings and %strusted proxies list%s. However, IP-based protection may not be reliable if your IP belongs to an ISP where thousands of users, including you, are connected to.');
427 $sSecurityInfoMsg = sprintf(
428 $sSecurityInfoMsg,
429 '[a@?page=servers&amp;mode=edit&amp;id=%1$d#tab_Server_config]',
430 '[/a]',
431 '[a@?page=form&amp;formset=Features#tab_Security]',
432 '[/a]'
434 $sServerAuthConfigMsg = __('You set the [kbd]config[/kbd] authentication type and included username and password for auto-login, which is not a desirable option for live hosts. Anyone who knows or guesses your phpMyAdmin URL can directly access your phpMyAdmin panel. Set %sauthentication type%s to [kbd]cookie[/kbd] or [kbd]http[/kbd].');
435 $sServerAuthConfigMsg = sprintf(
436 $sServerAuthConfigMsg,
437 '[a@?page=servers&amp;mode=edit&amp;id=%1$d#tab_Server]',
438 '[/a]'
440 $sZipDumpExportWarn = __('%sZip compression%s requires functions (%s) which are unavailable on this system.');
441 $sZipDumpExportWarn = sprintf(
442 $sZipDumpExportWarn,
443 '[a@?page=form&amp;formset=Features#tab_Import_export]',
444 '[/a]',
445 '%s'
447 $sZipDumpImportWarn = __('%sZip decompression%s requires functions (%s) which are unavailable on this system.');
448 $sZipDumpImportWarn = sprintf(
449 $sZipDumpImportWarn,
450 '[a@?page=form&amp;formset=Features#tab_Import_export]',
451 '[/a]',
452 '%s'
454 return array(
455 $sAllowArbitraryServerWarn, $sBlowfishSecretMsg, $sBZipDumpWarning,
456 $sDirectoryNotice, $sForceSSLNotice, $sGZipDumpWarning,
457 $sLoginCookieValidityWarn, $sLoginCookieValidityWarn2,
458 $sLoginCookieValidityWarn3, $sSecurityInfoMsg, $sServerAuthConfigMsg,
459 $sZipDumpExportWarn, $sZipDumpImportWarn
464 * Check configuration for login cookie
466 * @param string $sLoginCookieValidityWarn Warning 1 for login cookie validity
467 * @param string $sLoginCookieValidityWarn2 Warning 2 for login cookie validity
468 * @param string $sLoginCookieValidityWarn3 Warning 3 for login cookie validity
470 * @return void
472 protected function performConfigChecksLoginCookie(
473 $sLoginCookieValidityWarn, $sLoginCookieValidityWarn2,
474 $sLoginCookieValidityWarn3
477 // $cfg['LoginCookieValidity']
478 // value greater than session.gc_maxlifetime will cause
479 // random session invalidation after that time
480 $loginCookieValidity = $this->cfg->getValue('LoginCookieValidity');
481 if ($loginCookieValidity > ini_get('session.gc_maxlifetime')
483 PMA_messagesSet(
484 'error',
485 'LoginCookieValidity',
486 PMA_lang(PMA_langName('LoginCookieValidity')),
487 PMA_lang($sLoginCookieValidityWarn)
492 // $cfg['LoginCookieValidity']
493 // should be at most 1800 (30 min)
495 if ($loginCookieValidity > 1800) {
496 PMA_messagesSet(
497 'notice',
498 'LoginCookieValidity',
499 PMA_lang(PMA_langName('LoginCookieValidity')),
500 PMA_lang($sLoginCookieValidityWarn2)
505 // $cfg['LoginCookieValidity']
506 // $cfg['LoginCookieStore']
507 // LoginCookieValidity must be less or equal to LoginCookieStore
509 if (($this->cfg->getValue('LoginCookieStore') != 0)
510 && ($loginCookieValidity > $this->cfg->getValue('LoginCookieStore'))
512 PMA_messagesSet(
513 'error',
514 'LoginCookieValidity',
515 PMA_lang(PMA_langName('LoginCookieValidity')),
516 PMA_lang($sLoginCookieValidityWarn3)
522 * Check GZipDump configuration
524 * @param string $sBZipDumpWarn Warning for BZipDumpWarning
526 * @return void
528 protected function performConfigChecksServerBZipdump($sBZipDumpWarn)
531 // $cfg['BZipDump']
532 // requires bzip2 functions
534 if ($this->cfg->getValue('BZipDump')
535 && (!@function_exists('bzopen') || !@function_exists('bzcompress'))
537 $functions = @function_exists('bzopen')
538 ? '' :
539 'bzopen';
540 $functions .= @function_exists('bzcompress')
541 ? ''
542 : ($functions ? ', ' : '') . 'bzcompress';
543 PMA_messagesSet(
544 'error',
545 'BZipDump',
546 PMA_lang(PMA_langName('BZipDump')),
547 PMA_lang($sBZipDumpWarn, $functions)
553 * Check GZipDump configuration
555 * @param string $sGZipDumpWarn Warning for GZipDumpWarning
557 * @return void
559 protected function performConfigChecksServerGZipdump($sGZipDumpWarn)
562 // $cfg['GZipDump']
563 // requires zlib functions
565 if ($this->cfg->getValue('GZipDump')
566 && (@!function_exists('gzopen') || @!function_exists('gzencode'))
568 PMA_messagesSet(
569 'error',
570 'GZipDump',
571 PMA_lang(PMA_langName('GZipDump')),
572 PMA_lang($sGZipDumpWarn, 'gzencode')