f2e0761b062b6b1aa939d4c8da42be1073470775
[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 t3lib_BEfunc::deleteClause('be_users');
69 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
70 'uid, username, password',
71 'be_users',
72 $whereClause
73 );
74 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
75 $secure = TRUE;
76
77 // Check against salted password
78 if (t3lib_extMgm::isLoaded('saltedpasswords')) {
79 if (tx_saltedpasswords_div::isUsageEnabled('BE')) {
80 /** @var $saltingObject tx_saltedpasswords_salts */
81 $saltingObject = tx_saltedpasswords_salts_factory::getSaltingInstance($row['password']);
82 if (is_object($saltingObject)) {
83 if ($saltingObject->checkPassword('password', $row['password'])) {
84 $secure = FALSE;
85 }
86 }
87 }
88 }
89
90 // Check against plain MD5
91 if ($row['password'] === '5f4dcc3b5aa765d61d8327deb882cf99') {
92 $secure = FALSE;
93 }
94
95 if (!$secure) {
96 $value = $GLOBALS['LANG']->getLL('status_insecure');
97 $severity = tx_reports_reports_status_Status::ERROR;
98
99 $editUserAccountUrl = 'alt_doc.php?returnUrl=mod.php?M=tools_txreportsM1&edit[be_users][' . $row['uid'] . ']=edit';
100 $message = sprintf(
101 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.backend_admin'),
102 '<a href="' . $editUserAccountUrl . '">',
103 '</a>'
104 );
105 }
106 }
107 $GLOBALS['TYPO3_DB']->sql_free_result($res);
108
109 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
110 $GLOBALS['LANG']->getLL('status_adminUserAccount'), $value, $message, $severity
111 );
112 }
113
114 /**
115 * Checks whether the encryption key is empty.
116 *
117 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether the encryption key is empty or not
118 */
119 protected function getEncryptionKeyStatus() {
120 $value = $GLOBALS['LANG']->getLL('status_ok');
121 $message = '';
122 $severity = tx_reports_reports_status_Status::OK;
123
124 if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
125 $value = $GLOBALS['LANG']->getLL('status_insecure');
126 $severity = tx_reports_reports_status_Status::ERROR;
127 $url = 'install/index.php?redirect_url=index.php' . urlencode('?TYPO3_INSTALL[type]=config#set_encryptionKey');
128
129 $message = sprintf(
130 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_encryption'),
131 '<a href="' . $url . '">',
132 '</a>'
133 );
134 }
135
136 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
137 $GLOBALS['LANG']->getLL('status_encryptionKey'), $value, $message, $severity
138 );
139 }
140
141 /**
142 * Checks if fileDenyPattern was changed which is dangerous on Apache
143 *
144 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether the file deny pattern has changed
145 */
146 protected function getFileDenyPatternStatus() {
147 $value = $GLOBALS['LANG']->getLL('status_ok');
148 $message = '';
149 $severity = tx_reports_reports_status_Status::OK;
150
151 $defaultParts = t3lib_div::trimExplode('|', FILE_DENY_PATTERN_DEFAULT, TRUE);
152 $givenParts = t3lib_div::trimExplode('|', $GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'], TRUE);
153 $result = array_intersect($defaultParts, $givenParts);
154 if ($defaultParts !== $result) {
155 $value = $GLOBALS['LANG']->getLL('status_insecure');
156 $severity = tx_reports_reports_status_Status::ERROR;
157 $url = 'install/index.php?redirect_url=index.php' . urlencode('?TYPO3_INSTALL[type]=config#set_encryptionKey');
158
159 $message = sprintf(
160 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.file_deny_pattern_partsNotPresent'),
161 '<br /><pre>' . htmlspecialchars(FILE_DENY_PATTERN_DEFAULT) . '</pre><br />'
162 );
163 }
164
165 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
166 $GLOBALS['LANG']->getLL('status_fileDenyPattern'), $value, $message, $severity
167 );
168 }
169
170 /**
171 * Checks if fileDenyPattern allows to upload .htaccess files which is
172 * dangerous on Apache.
173 *
174 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether it's possible to upload .htaccess files
175 */
176 protected function getHtaccessUploadStatus() {
177 $value = $GLOBALS['LANG']->getLL('status_ok');
178 $message = '';
179 $severity = tx_reports_reports_status_Status::OK;
180
181 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'] != FILE_DENY_PATTERN_DEFAULT && t3lib_div::verifyFilenameAgainstDenyPattern('.htaccess')) {
182 $value = $GLOBALS['LANG']->getLL('status_insecure');
183 $severity = tx_reports_reports_status_Status::ERROR;
184 $message = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.file_deny_htaccess');
185 }
186
187 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
188 $GLOBALS['LANG']->getLL('status_htaccessUploadProtection'), $value, $message, $severity
189 );
190 }
191
192 /**
193 * Checks whether memcached is configured, if that's the case we asume it's also used.
194 *
195 * @return boolean TRUE if memcached is used, FALSE otherwise.
196 */
197 protected function isMemcachedUsed() {
198 $memcachedUsed = FALSE;
199
200 $memcachedServers = $this->getConfiguredMemcachedServers();
201 if (count($memcachedServers)) {
202 $memcachedUsed = TRUE;
203 }
204
205 return $memcachedUsed;
206 }
207
208
209 /**
210 * Executes commands like removing the Install Tool enable file.
211 *
212 * @return void
213 */
214 protected function executeAdminCommand() {
215 $command = t3lib_div::_GET('adminCmd');
216
217 switch ($command) {
218 case 'remove_ENABLE_INSTALL_TOOL':
219 unlink(PATH_site . 'typo3conf/ENABLE_INSTALL_TOOL');
220 break;
221 }
222 }
223
224 /**
225 * Checks whether the Install Tool password is set to its default value.
226 *
227 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing the security of the install tool password
228 */
229 protected function getInstallToolPasswordStatus() {
230 $value = $GLOBALS['LANG']->getLL('status_ok');
231 $message = '';
232 $severity = tx_reports_reports_status_Status::OK;
233
234 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'] == md5('joh316')) {
235 $value = $GLOBALS['LANG']->getLL('status_insecure');
236 $severity = tx_reports_reports_status_Status::ERROR;
237
238 $changeInstallToolPasswordUrl = 'install/index.php?redirect_url=index.php' .
239 urlencode('?TYPO3_INSTALL[type]=about');
240
241 $message = sprintf(
242 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_password'),
243 '<a href="' . $changeInstallToolPasswordUrl . '">',
244 '</a>'
245 );
246 }
247
248 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
249 $GLOBALS['LANG']->getLL('status_installToolPassword'), $value, $message, $severity
250 );
251 }
252
253 /**
254 * Checks whether the Install Tool password is set to its default value.
255 *
256 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing the security of the saltedpassswords extension
257 */
258 protected function getSaltedPasswordsStatus() {
259 $value = $GLOBALS['LANG']->getLL('status_ok');
260 $message = '';
261 $severity = tx_reports_reports_status_Status::OK;
262
263 if (!t3lib_extMgm::isLoaded('saltedpasswords')) {
264 $value = $GLOBALS['LANG']->getLL('status_insecure');
265 $severity = tx_reports_reports_status_Status::ERROR;
266 $message .= $GLOBALS['LANG']->getLL('status_saltedPasswords_notInstalled');
267 } else {
268 /** @var tx_saltedpasswords_emconfhelper $configCheck */
269 $configCheck = t3lib_div::makeInstance('tx_saltedpasswords_emconfhelper');
270 $message = '<p>' . $GLOBALS['LANG']->getLL('status_saltedPasswords_infoText') . '</p>';
271 $messageDetail = '';
272 $flashMessage = $configCheck->checkConfigurationBackend(array(), new t3lib_tsStyleConfig());
273
274 if (strpos($flashMessage, 'message-error') !== FALSE) {
275 $value = $GLOBALS['LANG']->getLL('status_insecure');
276 $severity = tx_reports_reports_status_Status::ERROR;
277 $messageDetail .= $flashMessage;
278 }
279 if (strpos($flashMessage, 'message-warning') !== FALSE ||
280 strpos($flashMessage, 'message-information') !== FALSE) {
281 $severity = tx_reports_reports_status_Status::WARNING;
282 $message .= $flashMessage;
283 }
284
285 $unsecureUserCount = tx_saltedpasswords_div::getNumberOfBackendUsersWithInsecurePassword();
286 if ($unsecureUserCount > 0) {
287 $value = $GLOBALS['LANG']->getLL('status_insecure');
288 $severity = tx_reports_reports_status_Status::ERROR;
289 $messageDetail .= '<div class="typo3-message message-warning">' .
290 $GLOBALS['LANG']->getLL('status_saltedPasswords_notAllPasswordsHashed') . '</div>';
291 }
292
293 $message .= $messageDetail;
294 if (empty($messageDetail)) {
295 $message = '';
296 }
297 }
298
299 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
300 $GLOBALS['LANG']->getLL('status_saltedPasswords'), $value, $message, $severity
301 );
302 }
303
304 /**
305 * Checks for the existance of the ENABLE_INSTALL_TOOL file.
306 *
307 * @return tx_reports_reports_status_Status An tx_reports_reports_status_Status object representing whether ENABLE_INSTALL_TOOL exists
308 */
309 protected function getInstallToolProtectionStatus() {
310 $enableInstallToolFile = PATH_site . 'typo3conf/ENABLE_INSTALL_TOOL';
311 $value = $GLOBALS['LANG']->getLL('status_disabled');
312 $message = '';
313 $severity = tx_reports_reports_status_Status::OK;
314
315 $enableInstallToolFileExists = is_file($enableInstallToolFile);
316
317 if ($enableInstallToolFileExists) {
318 if (trim(file_get_contents($enableInstallToolFile)) === 'KEEP_FILE') {
319 $severity = tx_reports_reports_status_Status::WARNING;
320 $disableInstallToolUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL') .
321 '&amp;adminCmd=remove_ENABLE_INSTALL_TOOL';
322 $value = $GLOBALS['LANG']->getLL('status_enabledPermanently');
323
324 $message = sprintf(
325 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_enabled'),
326 '<span style="white-space: nowrap;">' . $enableInstallToolFile . '</span>');
327 $message .= ' <a href="' . $disableInstallToolUrl . '">' .
328 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_enabled_cmd') .
329 '</a>';
330 } else {
331 $enableInstallToolFileTtl = filemtime($enableInstallToolFile) + 3600 - time();
332 if ($enableInstallToolFileTtl <= 0) {
333 unlink($enableInstallToolFile);
334 } else {
335 $severity = tx_reports_reports_status_Status::NOTICE;
336 $disableInstallToolUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL') .
337 '&amp;adminCmd=remove_ENABLE_INSTALL_TOOL';
338 $value = $GLOBALS['LANG']->getLL('status_enabledTemporarily');
339
340 $message = sprintf(
341 $GLOBALS['LANG']->getLL('status_installEnabledTemporarily'),
342 '<span style="white-space: nowrap;">' . $enableInstallToolFile . '</span>', floor($enableInstallToolFileTtl/60) );
343 $message .= ' <a href="' . $disableInstallToolUrl . '">' .
344 $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:warning.install_enabled_cmd') .
345 '</a>';
346 }
347 }
348 }
349
350 return t3lib_div::makeInstance('tx_reports_reports_status_Status',
351 $GLOBALS['LANG']->getLL('status_installTool'), $value, $message, $severity
352 );
353 }
354 }
355
356
357 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/reports/reports/status/class.tx_reports_reports_status_securitystatus.php'])) {
358 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/reports/reports/status/class.tx_reports_reports_status_securitystatus.php']);
359 }
360
361 ?>