[TASK] Re-work/simplify copyright header in PHP files - Part 8
[Packages/TYPO3.CMS.git] / typo3 / sysext / saltedpasswords / Classes / Utility / ExtensionManagerConfigurationUtility.php
1 <?php
2 namespace TYPO3\CMS\Saltedpasswords\Utility;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 use TYPO3\CMS\Core\Messaging\FlashMessage;
17
18 /**
19 * class providing configuration checks for saltedpasswords.
20 *
21 * @author Steffen Ritter <info@rs-websystems.de>
22 * @since 2009-09-04
23 */
24 class ExtensionManagerConfigurationUtility {
25
26 /**
27 * @var integer
28 */
29 protected $errorType = FlashMessage::OK;
30
31 /**
32 * @var string
33 */
34 protected $header;
35
36 /**
37 * @var string
38 */
39 protected $preText;
40
41 /**
42 * @var array
43 */
44 protected $problems = array();
45
46 /**
47 * @var array
48 */
49 protected $extConf = array();
50
51 /**
52 * Set the error level if no higher level
53 * is set already
54 *
55 * @param string $level One out of error, ok, warning, info
56 * @return void
57 */
58 private function setErrorLevel($level) {
59 switch ($level) {
60 case 'error':
61 $this->errorType = FlashMessage::ERROR;
62 $this->header = 'Errors found in your configuration';
63 $this->preText = 'SaltedPasswords will not work until these problems have been resolved:<br />';
64 break;
65 case 'warning':
66 if ($this->errorType < FlashMessage::ERROR) {
67 $this->errorType = FlashMessage::WARNING;
68 $this->header = 'Warnings about your configuration';
69 $this->preText = 'SaltedPasswords might behave different than expected:<br />';
70 }
71 break;
72 case 'info':
73 if ($this->errorType < FlashMessage::WARNING) {
74 $this->errorType = FlashMessage::INFO;
75 $this->header = 'Additional information';
76 $this->preText = '<br />';
77 }
78 break;
79 case 'ok':
80 // TODO: Remove INFO condition as it has lower importance
81 if ($this->errorType < FlashMessage::WARNING && $this->errorType != FlashMessage::INFO) {
82 $this->errorType = FlashMessage::OK;
83 $this->header = 'No errors were found';
84 $this->preText = 'SaltedPasswords has been configured correctly and works as expected.<br />';
85 }
86 break;
87 }
88 }
89
90 /**
91 * Renders the flash messages if problems have been found.
92 *
93 * @return string The flash message as HTML.
94 */
95 private function renderFlashMessage() {
96 $message = '';
97 // If there are problems, render them into an unordered list
98 if (count($this->problems) > 0) {
99 $message = '<ul>
100 <li>###PROBLEMS###</li>
101 </ul>';
102 $message = str_replace('###PROBLEMS###', implode('<br />&nbsp;</li><li>', $this->problems), $message);
103 if ($this->errorType > FlashMessage::OK) {
104 $message .= '<br />
105 Note, that a wrong configuration might have impact on the security of
106 your TYPO3 installation and the usability of the backend.';
107 }
108 }
109 if (empty($message)) {
110 $this->setErrorLevel('ok');
111 }
112 $message = $this->preText . $message;
113 $flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessage', $message, $this->header, $this->errorType);
114 return $flashMessage->render();
115 }
116
117 /**
118 * Initializes this object.
119 *
120 * @return void
121 */
122 private function init() {
123 $requestSetup = $this->processPostData((array) $_REQUEST['data']);
124 $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['saltedpasswords']);
125 $this->extConf['BE'] = array_merge((array) $extConf['BE.'], (array) $requestSetup['BE.']);
126 $this->extConf['FE'] = array_merge((array) $extConf['FE.'], (array) $requestSetup['FE.']);
127 $GLOBALS['LANG']->includeLLFile('EXT:saltedpasswords/locallang.xlf');
128 }
129
130 /**
131 * Checks the backend configuration and shows a message if necessary.
132 *
133 * @param array $params Field information to be rendered
134 * @param \TYPO3\CMS\Core\TypoScript\ConfigurationForm $pObj The calling parent object.
135 * @return string Messages as HTML if something needs to be reported
136 */
137 public function checkConfigurationBackend(array $params, $pObj) {
138 $this->init();
139 $extConf = $this->extConf['BE'];
140 // The backend is called over SSL
141 $SSL = $GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] > 0 && $GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel'] != 'superchallenged';
142 $rsaAuthLoaded = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('rsaauth');
143 // SSL configured?
144 if ($SSL) {
145 $this->setErrorLevel('ok');
146 $problems[] = 'The backend is configured to use SaltedPasswords over SSL.';
147 } elseif ($rsaAuthLoaded) {
148 if (trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) === 'rsa') {
149 if ($this->isRsaAuthBackendAvailable()) {
150 $this->setErrorLevel('ok');
151 $problems[] = 'The backend is configured to use SaltedPasswords with RSA authentication.';
152 } else {
153 // This means that login would fail because rsaauth is not working properly
154 $this->setErrorLevel('error');
155 $problems[] = '<strong>Using the extension "rsaauth" is not possible, as no encryption backend ' .
156 'is available. Please install and configure the PHP extension "openssl". ' .
157 'See <a href="http://php.net/manual/en/openssl.installation.php" target="_blank">PHP.net</a></strong>.';
158 }
159 } else {
160 // This means that rsaauth is enabled but not used
161 $this->setErrorLevel('warning');
162 $problems[] = 'The "rsaauth" extension is installed, but TYPO3 is not configured to use it during login.
163 Use the Install Tool to set the Login Security Level for the backend to "rsa"
164 ($TYPO3_CONF_VARS[\'BE\'][\'loginSecurityLevel\'])';
165 }
166 } else {
167 // This means that we don't use any encryption method
168 $this->setErrorLevel('warning');
169 $problems[] = 'SaltedPasswords is used without any transfer encryption, this means your passwords are sent in plain text.
170 Please install rsaauth to secure your passwords submits.<br />
171 <ul>
172 <li>Install the "rsaauth" extension and use the Install Tool to set the
173 Login Security Level for the backend to "rsa"
174 ($TYPO3_CONF_VARS[\'BE\'][\'loginSecurityLevel\'])</li>
175
176 <li>If you have the option to use SSL, you can also configure your
177 backend for SSL usage:<br />
178 Use the Install Tool to set the Security-Level for the backend
179 to "normal" ($TYPO3_CONF_VARS[\'BE\'][\'loginSecurityLevel\']) and
180 the SSL-locking option to a value greater than "0"
181 (see description - $TYPO3_CONF_VARS[\'BE\'][\'lockSSL\'])</li>
182 </ul>
183 <br />
184 It is also possible to use "lockSSL" and "rsa" Login Security Level at the same
185 time.';
186 }
187 // Only saltedpasswords as authsservice
188 if ($extConf['onlyAuthService']) {
189 // Warn user that the combination with "forceSalted" may lock him out from Backend
190 if ($extConf['forceSalted']) {
191 $this->setErrorLevel('warning');
192 $problems[] = 'SaltedPasswords has been configured to be the only authentication service for
193 the backend. Additionally, usage of salted passwords is enforced (forceSalted).
194 The result is that there is no chance to login with users not having a salted
195 password hash.<br />
196 <strong><i>WARNING:</i></strong> This may lock you out of the backend!';
197 } else {
198 // Inform the user that things like openid won't work anymore
199 $this->setErrorLevel('info');
200 $problems[] = 'SaltedPasswords has been configured to be the only authentication service for
201 the backend. This means that other services like "ipauth", "openid", etc. will
202 be ignored (except "rsauth", which is implicitely used).';
203 }
204 }
205 // forceSalted is set
206 if ($extConf['forceSalted'] && !$extConf['onlyAuthService']) {
207 $this->setErrorLevel('info');
208 $problems[] = 'SaltedPasswords has been configured to enforce salted passwords (forceSalted).
209 <br />
210 This means that only passwords in the format of this extension will succeed for
211 login.';
212 }
213 // updatePasswd wont work with "forceSalted"
214 if ($extConf['updatePasswd'] && $extConf['forceSalted']) {
215 $this->setErrorLevel('error');
216 $problems[] = 'SaltedPasswords is configured wrong and will not work as expected:<br />
217 It is not possible to set "updatePasswd" and "forceSalted" at the same time.
218 Please disable either one of them.';
219 }
220 // Check if the configured hash-method is available on system
221 $instance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(NULL, 'BE');
222 if ($instance === NULL || !$instance->isAvailable()) {
223 $this->setErrorLevel('error');
224 $problems[] = 'The selected method for hashing your salted passwords is not available on this
225 system! Please check your configuration.';
226 }
227 $this->problems = $problems;
228 return $this->renderFlashMessage();
229 }
230
231 /**
232 * Checks if rsaauth is able to obtain a backend
233 *
234 * @return boolean
235 */
236 protected function isRsaAuthBackendAvailable() {
237 /**
238 * Try to instantiate an RSAauth backend. If this does not work, it means that OpenSSL is not usable
239 *
240 * @var $rsaauthBackendFactory \TYPO3\CMS\Rsaauth\Backend\BackendFactory
241 */
242 $rsaauthBackendFactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Rsaauth\\Backend\\BackendFactory');
243 $backend = $rsaauthBackendFactory->getBackend();
244 return $backend !== NULL;
245 }
246
247 /**
248 * Checks the frontend configuration and shows a message if necessary.
249 *
250 * @param array $params Field information to be rendered
251 * @param \TYPO3\CMS\Core\TypoScript\ConfigurationForm $pObj The calling parent object.
252 * @return string Messages as HTML if something needs to be reported
253 */
254 public function checkConfigurationFrontend(array $params, $pObj) {
255 $this->init();
256 $extConf = $this->extConf['FE'];
257 $problems = array();
258 if ($extConf['enabled']) {
259 // Inform the user if securityLevel in FE is challenged or blank --> extension won't work
260 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::inList('normal,rsa', $GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel'])) {
261 $this->setErrorLevel('info');
262 $problems[] = '<strong>IMPORTANT:</strong><br />
263 Frontend requirements for SaltedPasswords are not met, therefore the
264 authentication will not work even if it was explicitly enabled for frontend
265 usage:<br />
266 <ul>
267 <li>Install the "rsaauth" extension and use the Install Tool to set the
268 Login Security Level for the frontend to "rsa"
269 ($TYPO3_CONF_VARS[\'FE\'][\'loginSecurityLevel\'])</li>
270
271 <li>Alternatively, use the Install Tool to set the Login Security Level
272 for the frontend to "normal"
273 ($TYPO3_CONF_VARS[\'FE\'][\'loginSecurityLevel\'])</li>
274 </ul>
275 <br />
276 Make sure that the Login Security Level is not set to "" or "challenged"!';
277 } elseif (trim($GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel']) === 'rsa') {
278 if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('rsaauth')) {
279 if ($this->isRsaAuthBackendAvailable()) {
280 $this->setErrorLevel('ok');
281 $problems[] = 'The frontend is configured to use SaltedPasswords with RSA authentication.';
282 } else {
283 // This means that login would fail because rsaauth is not working properly
284 $this->setErrorLevel('error');
285 $problems[] = '<strong>Using the extension "rsaauth" is not possible, as no encryption backend '
286 . 'is available. Please install and configure the PHP extension "openssl". '
287 . 'See <a href="http://php.net/manual/en/openssl.installation.php" target="_blank">PHP.net</a></strong>.';
288 }
289 } else {
290 // Rsaauth is not installed but configured to be used
291 $this->setErrorLevel('warning');
292 $problems[] = 'The "rsaauth" extension is not installed, but TYPO3 CMS is configured to use it.'
293 . ' Either install the extension or adapt the configuration by setting [FE][loginSecurityLevel]'
294 . ' to "normal" in the Install Tool.';
295 }
296 }
297 // Only saltedpasswords as authsservice
298 if ($extConf['onlyAuthService']) {
299 // Warn user taht the combination with "forceSalted" may lock him out from frontend
300 if ($extConf['forceSalted']) {
301 $this->setErrorLevel('warning');
302 $problems[] = 'SaltedPasswords has been configured to enforce salted passwords (forceSalted).
303 <br />
304 This means that only passwords in the format of this extension will succeed for
305 login.<br />
306 <strong><i>IMPORTANT:</i></strong> Because of this, it is not possible to login with
307 users not having a salted password hash (e.g. existing frontend users).';
308 } else {
309 // Inform the user that things like openid won't work anymore
310 $this->setErrorLevel('info');
311 $problems[] = 'SaltedPasswords has been configured to be the only authentication service for
312 frontend logins. This means that other services like "ipauth", "openid", etc.
313 will be ignored.';
314 }
315 }
316 // forceSalted is set
317 if ($extConf['forceSalted'] && !$extConf['onlyAuthService']) {
318 $this->setErrorLevel('warning');
319 $problems[] = 'SaltedPasswords has been configured to enforce salted passwords (forceSalted).
320 <br />
321 This means that only passwords in the format of this extension will succeed for
322 login.<br />
323 <strong><i>IMPORTANT:</i></strong> This has the effect that passwords that were set
324 before SaltedPasswords was used will not work (in fact, they need to be
325 redefined).';
326 }
327 // updatePasswd wont work with "forceSalted"
328 if ($extConf['updatePasswd'] && $extConf['forceSalted']) {
329 $this->setErrorLevel('error');
330 $problems[] = 'SaltedPasswords is configured wrong and will not work as expected:<br />
331 It is not possible to set "updatePasswd" and "forceSalted" at the same time.
332 Please disable either one of them.';
333 }
334 } else {
335 // Not enabled warning
336 $this->setErrorLevel('info');
337 $problems[] = 'SaltedPasswords has been disabled for frontend users.';
338 }
339 $this->problems = $problems;
340 return $this->renderFlashMessage();
341 }
342
343 /**
344 * Renders a selector element that allows to select the hash method to be used.
345 *
346 * @param array $params Field information to be rendered
347 * @param \TYPO3\CMS\Core\TypoScript\ConfigurationForm $pObj The calling parent object.
348 * @param string $disposal The configuration disposal ('FE' or 'BE')
349 * @return string The HTML selector
350 */
351 protected function buildHashMethodSelector(array $params, $pObj, $disposal) {
352 $this->init();
353 $propertyName = $params['propertyName'];
354 $unknownVariablePleaseRenameMe = '\'' . substr(md5($propertyName), 0, 10) . '\'';
355 $p_field = '';
356 $registeredMethods = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getRegisteredSaltedHashingMethods();
357 foreach ($registeredMethods as $class => $reference) {
358 $classInstance = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($reference, 'tx_');
359 if ($classInstance instanceof \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface && $classInstance->isAvailable()) {
360 $sel = $this->extConf[$disposal]['saltedPWHashingMethod'] == $class ? ' selected="selected" ' : '';
361 $label = 'ext.saltedpasswords.title.' . strtolower(end(explode('\\', $class)));
362 $p_field .= '<option value="' . htmlspecialchars($class) . '"' . $sel . '>' . $GLOBALS['LANG']->getLL($label) . '</option>';
363 }
364 }
365 $p_field = '<select id="' . $propertyName . '" name="' . $params['fieldName'] . '" onChange="uFormUrl(' . $unknownVariablePleaseRenameMe . ')">' . $p_field . '</select>';
366 return $p_field;
367 }
368
369 /**
370 * Renders a selector element that allows to select the hash method to be used (frontend disposal).
371 *
372 * @param array $params Field information to be rendered
373 * @param \TYPO3\CMS\Core\TypoScript\ConfigurationForm $pObj The calling parent object.
374 * @return string The HTML selector
375 */
376 public function buildHashMethodSelectorFE(array $params, $pObj) {
377 return $this->buildHashMethodSelector($params, $pObj, 'FE');
378 }
379
380 /**
381 * Renders a selector element that allows to select the hash method to be used (backend disposal)
382 *
383 * @param array $params Field information to be rendered
384 * @param \TYPO3\CMS\Core\TypoScript\ConfigurationForm $pObj The calling parent object.
385 * @return string The HTML selector
386 */
387 public function buildHashMethodSelectorBE(array $params, $pObj) {
388 return $this->buildHashMethodSelector($params, $pObj, 'BE');
389 }
390
391 /**
392 * Processes the information submitted by the user using a POST request and
393 * transforms it to a TypoScript node notation.
394 *
395 * @param array $postArray Incoming POST information
396 * @return array Processed and transformed POST information
397 */
398 private function processPostData(array $postArray = array()) {
399 foreach ($postArray as $key => $value) {
400 // TODO: Explain
401 $parts = explode('.', $key, 2);
402 if (count($parts) == 2) {
403 // TODO: Explain
404 $value = $this->processPostData(array($parts[1] => $value));
405 $postArray[$parts[0] . '.'] = array_merge((array) $postArray[($parts[0] . '.')], $value);
406 } else {
407 // TODO: Explain
408 $postArray[$parts[0]] = $value;
409 }
410 }
411 return $postArray;
412 }
413
414 }