[TASK] Implement check for saltedpasswords in reports module
[Packages/TYPO3.CMS.git] / typo3 / sysext / reports / reports / status / class.tx_reports_reports_status_securitystatus.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009-2011 Ingo Renner <ingo@typo3.org>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25
26 /**
27 * Performs several checks about the system's health
28 *
29 * @author Ingo Renner <ingo@typo3.org>
30 * @package TYPO3
31 * @subpackage reports
32 */
33 class tx_reports_reports_status_SecurityStatus implements tx_reports_StatusProvider {
34
35 /**
36 * Determines the Install Tool's status, mainly concerning its protection.
37 *
38 * @return array List of statuses
39 * @see typo3/sysext/reports/interfaces/tx_reports_StatusProvider::getStatus()
40 */
41 public function getStatus() {
42 $this->executeAdminCommand();
43
44 $statuses = array(
45 'adminUserAccount' => $this->getAdminAccountStatus(),
46 'encryptionKeyEmpty' => $this->getEncryptionKeyStatus(),
47 'fileDenyPattern' => $this->getFileDenyPatternStatus(),
48 'htaccessUpload' => $this->getHtaccessUploadStatus(),
49 'installToolEnabled' => $this->getInstallToolProtectionStatus(),
50 'installToolPassword' => $this->getInstallToolPasswordStatus(),
51 'saltedpasswords' => $this->getSaltedPasswordsStatus()
52 );
53
54 return $statuses;
55 }
56
57 /**
58 * Checks whether a an BE user account named admin with default password exists.
59 *
60 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether a default admin account exists
61 */
62 protected function getAdminAccountStatus() {
63 $value = $GLOBALS['LANG']->getLL('status_ok');
64 $message = '';
65 $severity = tx_reports_reports_status_Status::OK;
66
67 $whereClause = 'username = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr('admin', 'be_users')
68 . ' AND password = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr('5f4dcc3b5aa765d61d8327deb882cf99', 'be_users')
69 . t3lib_BEfunc::deleteClause('be_users');
70 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
71 'uid, username, password',
72 'be_users',
73 $whereClause
74 );
75 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
76 $value = $GLOBALS['LANG']->getLL('status_insecure');
77 $severity = tx_reports_reports_status_Status::ERROR;
78
79 $editUserAccountUrl = 'alt_doc.php?returnUrl=mod.php?M=tools_txreportsM1&edit[be_users][' . $row['uid'] . ']=edit';
80 $message = sprintf(
81 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.backend_admin'),
82 '<a href="' . $editUserAccountUrl . '">',
83 '</a>'
84 );
85 }
86 $GLOBALS['TYPO3_DB']->sql_free_result($res);
87
88 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
89 $GLOBALS['LANG']->getLL('status_adminUserAccount'), $value, $message, $severity
90 );
91 }
92
93 /**
94 * Checks whether the encryption key is empty.
95 *
96 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether the encryption key is empty or not
97 */
98 protected function getEncryptionKeyStatus() {
99 $value = $GLOBALS['LANG']->getLL('status_ok');
100 $message = '';
101 $severity = tx_reports_reports_status_Status::OK;
102
103 if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
104 $value = $GLOBALS['LANG']->getLL('status_insecure');
105 $severity = tx_reports_reports_status_Status::ERROR;
106
107 $url = 'install/index.php?redirect_url=index.php'
108 . urlencode('?TYPO3_INSTALL[type]=config#set_encryptionKey');
109
110 $message = sprintf(
111 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_encryption'),
112 '<a href="' . $url . '">',
113 '</a>'
114 );
115 }
116
117 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
118 $GLOBALS['LANG']->getLL('status_encryptionKey'), $value, $message, $severity
119 );
120 }
121
122 /**
123 * Checks if fileDenyPattern was changed which is dangerous on Apache
124 *
125 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether the file deny pattern has changed
126 */
127 protected function getFileDenyPatternStatus() {
128 $value = $GLOBALS['LANG']->getLL('status_ok');
129 $message = '';
130 $severity = tx_reports_reports_status_Status::OK;
131
132 $defaultParts = t3lib_div::trimExplode('|', FILE_DENY_PATTERN_DEFAULT, TRUE);
133 $givenParts = t3lib_div::trimExplode('|', $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'], TRUE);
134 $result = array_intersect($defaultParts, $givenParts);
135 if ($defaultParts !== $result) {
136 $value = $GLOBALS['LANG']->getLL('status_insecure');
137 $severity = tx_reports_reports_status_Status::ERROR;
138
139 $url = 'install/index.php?redirect_url=index.php'
140 . urlencode('?TYPO3_INSTALL[type]=config#set_encryptionKey');
141
142 $message = sprintf(
143 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.file_deny_pattern_partsNotPresent'),
144 '<br /><pre>'
145 . htmlspecialchars(FILE_DENY_PATTERN_DEFAULT)
146 . '</pre><br />'
147 );
148 }
149
150 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
151 $GLOBALS['LANG']->getLL('status_fileDenyPattern'), $value, $message, $severity
152 );
153 }
154
155 /**
156 * Checks if fileDenyPattern allows to upload .htaccess files which is
157 * dangerous on Apache.
158 *
159 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether it's possible to upload .htaccess files
160 */
161 protected function getHtaccessUploadStatus() {
162 $value = $GLOBALS['LANG']->getLL('status_ok');
163 $message = '';
164 $severity = tx_reports_reports_status_Status::OK;
165
166 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'] != FILE_DENY_PATTERN_DEFAULT && t3lib_div::verifyFilenameAgainstDenyPattern('.htaccess')) {
167 $value = $GLOBALS['LANG']->getLL('status_insecure');
168 $severity = tx_reports_reports_status_Status::ERROR;
169 $message = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.file_deny_htaccess');
170 }
171
172 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
173 $GLOBALS['LANG']->getLL('status_htaccessUploadProtection'), $value, $message, $severity
174 );
175 }
176
177 /**
178 * Checks whether memcached is configured, if that's the case we asume it's also used.
179 *
180 * @return boolean TRUE if memcached is used, FALSE otherwise.
181 */
182 protected function isMemcachedUsed() {
183 $memcachedUsed = FALSE;
184
185 $memcachedServers = $this->getConfiguredMemcachedServers();
186 if (count($memcachedServers)) {
187 $memcachedUsed = TRUE;
188 }
189
190 return $memcachedUsed;
191 }
192
193
194 /**
195 * Executes commands like removing the Install Tool enable file.
196 *
197 * @return void
198 */
199 protected function executeAdminCommand() {
200 $command = t3lib_div::_GET('adminCmd');
201
202 switch ($command) {
203 case 'remove_ENABLE_INSTALL_TOOL':
204 unlink(PATH_site . 'typo3conf/ENABLE_INSTALL_TOOL');
205 break;
206 }
207 }
208
209 /**
210 * Checks whether the Install Tool password is set to its default value.
211 *
212 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing the security of the install tool password
213 */
214 protected function getInstallToolPasswordStatus() {
215 $value = $GLOBALS['LANG']->getLL('status_ok');
216 $message = '';
217 $severity = tx_reports_reports_status_Status::OK;
218
219 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'] == md5('joh316')) {
220 $value = $GLOBALS['LANG']->getLL('status_insecure');
221 $severity = tx_reports_reports_status_Status::ERROR;
222
223 $changeInstallToolPasswordUrl = 'install/index.php?redirect_url=index.php'
224 . urlencode('?TYPO3_INSTALL[type]=about');
225
226 $message = sprintf(
227 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_password'),
228 '<a href="' . $changeInstallToolPasswordUrl . '">',
229 '</a>'
230 );
231 }
232
233 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
234 $GLOBALS['LANG']->getLL('status_installToolPassword'), $value, $message, $severity
235 );
236 }
237
238 /**
239 * Checks whether the Install Tool password is set to its default value.
240 *
241 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing the security of the saltedpassswords extension
242 */
243 protected function getSaltedPasswordsStatus() {
244 $value = $GLOBALS['LANG']->getLL('status_ok');
245 $message = '';
246 $severity = tx_reports_reports_status_Status::OK;
247
248 if (!t3lib_extMgm::isLoaded('saltedpasswords')) {
249 $value = $GLOBALS['LANG']->getLL('status_insecure');
250 $severity = tx_reports_reports_status_Status::ERROR;
251 $message .= $GLOBALS['LANG']->getLL('status_saltedPasswords_notInstalled');
252 } else {
253 /** @var tx_saltedpasswords_emconfhelper $configCheck */
254 $configCheck = t3lib_div::makeInstance('tx_saltedpasswords_emconfhelper');
255 $message .= '<p>' . $GLOBALS['LANG']->getLL('status_saltedPasswords_infoText') . '</p>';
256 $flashMessage = $configCheck->checkConfigurationBackend(array(), new t3lib_tsStyleConfig());
257
258 if (strpos($flashMessage, 'message-error') !== FALSE ||
259 strpos($flashMessage, 'message-warning') !== FALSE ||
260 strpos($flashMessage, 'message-information') !== FALSE
261 ) {
262 $value = $GLOBALS['LANG']->getLL('status_insecure');
263 $severity = tx_reports_reports_status_Status::ERROR;
264 $message .= $flashMessage;
265 }
266
267 $unsecureUserCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
268 '*',
269 'be_users',
270 'password NOT LIKE ' . $GLOBALS['TYPO3_DB']->fullQuoteStr('$%', 'be_users')
271 . ' AND password NOT LIKE ' . $GLOBALS['TYPO3_DB']->fullQuoteStr('M$%', 'be_users')
272 );
273 if ($unsecureUserCount > 0) {
274 $value = $GLOBALS['LANG']->getLL('status_insecure');
275 $severity = tx_reports_reports_status_Status::ERROR;
276 $message .= '<div class="typo3-message message-warning">' .
277 $GLOBALS['LANG']->getLL('status_saltedPasswords_notAllPasswordsHashed') .'</div>';
278 }
279 }
280
281 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
282 $GLOBALS['LANG']->getLL('status_saltedPasswords'), $value, $message, $severity
283 );
284 }
285
286 /**
287 * Checks for the existance of the ENABLE_INSTALL_TOOL file.
288 *
289 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether ENABLE_INSTALL_TOOL exists
290 */
291 protected function getInstallToolProtectionStatus() {
292 $enableInstallToolFile = PATH_site . 'typo3conf/ENABLE_INSTALL_TOOL';
293 $value = $GLOBALS['LANG']->getLL('status_disabled');
294 $message = '';
295 $severity = tx_reports_reports_status_Status::OK;
296
297 $enableInstallToolFileExists = is_file($enableInstallToolFile);
298
299 if ($enableInstallToolFileExists) {
300
301 if (trim(file_get_contents($enableInstallToolFile)) === 'KEEP_FILE') {
302
303 $severity = tx_reports_reports_status_Status::WARNING;
304
305 $disableInstallToolUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL')
306 . '&amp;adminCmd=remove_ENABLE_INSTALL_TOOL';
307
308 $value = $GLOBALS['LANG']->getLL('status_enabledPermanently');
309
310 $message = sprintf(
311 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_enabled'),
312 '<span style="white-space: nowrap;">' . $enableInstallToolFile . '</span>');
313 $message .= ' <a href="' . $disableInstallToolUrl . '">'
314 . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_enabled_cmd')
315 . '</a>';
316
317 } else {
318
319 $enableInstallToolFileTtl = filemtime($enableInstallToolFile) + 3600 - time();
320
321 if ($enableInstallToolFileTtl <= 0) {
322
323 unlink($enableInstallToolFile);
324
325 } else {
326
327 $severity = tx_reports_reports_status_Status::NOTICE;
328
329 $disableInstallToolUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL')
330 . '&amp;adminCmd=remove_ENABLE_INSTALL_TOOL';
331
332 $value = $GLOBALS['LANG']->getLL('status_enabledTemporarily');
333
334 $message = sprintf(
335 $GLOBALS['LANG']->getLL('status_installEnabledTemporarily'),
336 '<span style="white-space: nowrap;">' . $enableInstallToolFile . '</span>', floor($enableInstallToolFileTtl/60) );
337 $message .= ' <a href="' . $disableInstallToolUrl . '">'
338 . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_enabled_cmd')
339 . '</a>';
340 }
341 }
342 }
343
344 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
345 $GLOBALS['LANG']->getLL('status_installTool'), $value, $message, $severity
346 );
347 }
348
349 }
350
351
352 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/reports/reports/status/class.tx_reports_reports_status_securitystatus.php'])) {
353 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/reports/reports/status/class.tx_reports_reports_status_securitystatus.php']);
354 }
355
356 ?>