TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
ExtensionManagerConfigurationUtility.php
Go to the documentation of this file.
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 
20 
25 {
30 
34  protected $header;
35 
39  protected $preText;
40 
44  protected $problems = [];
45 
49  protected $extConf = [];
50 
58  protected function setErrorLevel($level)
59  {
60  $lang = $this->getLanguageService();
61  switch ($level) {
62  case 'error':
63  $this->errorType = FlashMessage::ERROR;
64  $this->header = $lang->getLL('ext.saltedpasswords.configuration.header.errorsFound');
65  $this->preText = $lang->getLL('ext.saltedpasswords.configuration.message.errorsFound') . '<br />';
66  break;
67  case 'warning':
68  if ($this->errorType < FlashMessage::ERROR) {
69  $this->errorType = FlashMessage::WARNING;
70  $this->header = $lang->getLL('ext.saltedpasswords.configuration.header.warningsFound');
71  $this->preText = $lang->getLL('ext.saltedpasswords.configuration.message.warningsFound') . '<br />';
72  }
73  break;
74  case 'info':
75  if ($this->errorType < FlashMessage::WARNING) {
76  $this->errorType = FlashMessage::INFO;
77  $this->header = $lang->getLL('ext.saltedpasswords.configuration.header.additionalInformation');
78  $this->preText = '<br />';
79  }
80  break;
81  case 'ok':
82  // @todo Remove INFO condition as it has lower importance
83  if ($this->errorType < FlashMessage::WARNING && $this->errorType != FlashMessage::INFO) {
84  $this->errorType = FlashMessage::OK;
85  $this->header = $lang->getLL('ext.saltedpasswords.configuration.header.noErrorsFound');
86  $this->preText = $lang->getLL('ext.saltedpasswords.configuration.message.noErrorsFound') . '<br />';
87  }
88  break;
89  default:
90  }
91  }
92 
98  protected function renderMessage()
99  {
100  $message = '';
101  // If there are problems, render them into an unordered list
102  if (!empty($this->problems)) {
103  $message = '<ul><li>###PROBLEMS###</li></ul>';
104  $message = str_replace('###PROBLEMS###', implode('<br />&nbsp;</li><li>', $this->problems), $message);
105  if ($this->errorType > FlashMessage::OK) {
106  $message .= '<br />' .
107  $this->getLanguageService()->getLL('ext.saltedpasswords.configuration.message.securityWarning');
108  }
109  }
110  if (empty($message)) {
111  $this->setErrorLevel('ok');
112  }
113  $message = $this->preText . $message;
114 
115  $class = 'default';
116  switch ($this->errorType) {
118  $class = 'notice';
119  break;
120  case FlashMessage::INFO:
121  $class = 'info';
122  break;
123  case FlashMessage::OK:
124  $class = 'success';
125  break;
127  $class = 'warning';
128  break;
129  case FlashMessage::ERROR:
130  $class = 'danger';
131  break;
132  default:
133  }
134  $html = '<div class="panel panel-' . $class . '">' .
135  '<div class="panel-heading">' . $this->header . '</div>' .
136  '<div class="panel-body">' . $message . '</div>' .
137  '</div>';
138  return [
139  'errorType' => $this->errorType,
140  'html' => $html
141  ];
142  }
143 
149  private function init()
150  {
151  $requestSetup = $this->processPostData((array) $_REQUEST['data']);
152  $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['saltedpasswords'], ['allowed_classes' => false]);
153  $this->extConf['BE'] = array_merge((array)$extConf['BE.'], (array)$requestSetup['BE.']);
154  $this->extConf['FE'] = array_merge((array)$extConf['FE.'], (array)$requestSetup['FE.']);
155  $this->getLanguageService()->includeLLFile('EXT:saltedpasswords/Resources/Private/Language/locallang.xlf');
156  }
157 
167  public function checkConfigurationBackend(array $params, $pObj)
168  {
169  $this->init();
170  $extConf = $this->extConf['BE'];
171  // The backend is called over SSL
172  $isBackendCalledOverSsl = (bool)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'];
173  $rsaAuthLoaded = ExtensionManagementUtility::isLoaded('rsaauth');
174  // SSL configured?
175  $lang = $this->getLanguageService();
176  if ($isBackendCalledOverSsl) {
177  $this->setErrorLevel('ok');
178  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.backendSsl');
179  } elseif ($rsaAuthLoaded) {
180  $loginSecurityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) ?: 'normal';
181  if ($loginSecurityLevel === 'rsa') {
182  if ($this->isRsaAuthBackendAvailable()) {
183  $this->setErrorLevel('ok');
184  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.backendRsa');
185  } else {
186  // This means that login would fail because rsaauth is not working properly
187  $this->setErrorLevel('error');
188  $problems[] = '<strong>' .
189  $lang->getLL('ext.saltedpasswords.configuration.message.openSslMissing') .
190  '<a href="http://php.net/manual/en/openssl.installation.php" target="_blank">PHP.net</a></strong>.';
191  }
192  } else {
193  // This means that rsaauth is enabled but not used
194  $this->setErrorLevel('warning');
195  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.backendSecurityLevelNotRsa');
196  }
197  } else {
198  // This means that we don't use any encryption method
199  $this->setErrorLevel('warning');
200  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.rsaInstructionsIntro') . '<br />
201  <ul>
202  <li>' . $lang->getLL('ext.saltedpasswords.configuration.message.rsaInstructionsFirstItem') . '</li>
203 
204  <li>' . nl2br($lang->getLL('ext.saltedpasswords.configuration.message.rsaInstructionsSecondItem')) .
205  '</li>
206  </ul>
207  <br />
208  ' . $lang->getLL('ext.saltedpasswords.configuration.message.rsaInstructionsFootnote');
209  }
210  // Only saltedpasswords as authsservice
211  if ($extConf['onlyAuthService']) {
212  // Warn user that the combination with "forceSalted" may lock him
213  // out from Backend
214  if ($extConf['forceSalted']) {
215  $this->setErrorLevel('warning');
216  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.warningForceSalted') . '<br />
217  <strong><i>' . $lang->getLL('ext.saltedpasswords.configuration.label.warning') . '</i></strong> ' .
218  $lang->getLL('ext.saltedpasswords.configuration.message.warningForceSaltedNoteForBackend');
219  } else {
220  // Inform the user that things like openid won't work anymore
221  $this->setErrorLevel('info');
222  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.infoOnlyBackendAuthService');
223  }
224  }
225  // forceSalted is set
226  if ($extConf['forceSalted'] && !$extConf['onlyAuthService']) {
227  $this->setErrorLevel('info');
228  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.infoForceSalted') .
229  ' <br /> ' . $lang->getLL('ext.saltedpasswords.configuration.message.infoForceSaltedNote');
230  }
231  // updatePasswd wont work with "forceSalted"
232  if ($extConf['updatePasswd'] && $extConf['forceSalted']) {
233  $this->setErrorLevel('error');
234  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.errorForceSaltedAndUpdatePassword') .
235  '<br /> ' .
236  $lang->getLL('ext.saltedpasswords.configuration.message.errorForceSaltedAndUpdatePasswordReason');
237  }
238  // Check if the configured hash-method is available on system
240  if ($instance === null || !$instance->isAvailable()) {
241  $this->setErrorLevel('error');
242  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.errorHashMethodNotAvailable');
243  }
244  $this->problems = $problems;
245  $result = $this->renderMessage();
246  if (!empty($params['propertyName'])) {
247  return $result['html'];
248  }
249  return $result;
250  }
251 
257  protected function isRsaAuthBackendAvailable()
258  {
259  // Try to instantiate an RSAauth backend. If this does not work,
260  // it means that OpenSSL is not usable
262  $rsaauthBackendFactory = GeneralUtility::makeInstance(\TYPO3\CMS\Rsaauth\Backend\BackendFactory::class);
263  $backend = $rsaauthBackendFactory->getBackend();
264  return $backend !== null;
265  }
266 
276  public function checkConfigurationFrontend(array $params, $pObj)
277  {
278  $this->init();
279  $extConf = $this->extConf['FE'];
280  $problems = [];
281  $lang = $this->getLanguageService();
282  if ($extConf['enabled']) {
283  $loginSecurityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel']) ?: 'normal';
284  if ($loginSecurityLevel !== 'normal' && $loginSecurityLevel !== 'rsa') {
285  $this->setErrorLevel('info');
286  $problems[] = '<strong>' . $lang->getLL('ext.saltedpasswords.configuration.label.important') .
287  '</strong><br /> ' .
288  $lang->getLL('ext.saltedpasswords.configuration.message.infoLoginSecurityLevelDifferent') .
289  '<br />
290  <ul>
291  <li>' .
292  $lang->getLL('ext.saltedpasswords.configuration.message.infoLoginSecurityLevelDifferentFirstItem') .
293  '</li>
294 
295  <li>' .
296  $lang->getLL('ext.saltedpasswords.configuration.message.infoLoginSecurityLevelDifferentSecondItem') .
297  '</li>
298  </ul>
299  <br />
300  ' . $lang->getLL('ext.saltedpasswords.configuration.message.infoLoginSecurityLevelDifferentNote');
301  } elseif ($loginSecurityLevel === 'rsa') {
302  if (ExtensionManagementUtility::isLoaded('rsaauth')) {
303  if ($this->isRsaAuthBackendAvailable()) {
304  $this->setErrorLevel('ok');
305  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.okFeRsaauthLoaded');
306  } else {
307  // This means that login would fail because rsaauth is not working properly
308  $this->setErrorLevel('error');
309  $problems[] = '<strong>' . $lang->getLL('ext.saltedpasswords.configuration.message.openSslMissing') .
310  ' <a href="http://php.net/manual/en/openssl.installation.php" target="_blank">PHP.net</a></strong>.';
311  }
312  } else {
313  // Rsaauth is not installed but configured to be used
314  $this->setErrorLevel('warning');
315  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.warningRsaauthNotInstalledButConfigured');
316  }
317  }
318  // Only saltedpasswords as authsservice
319  if ($extConf['onlyAuthService']) {
320  // Warn user that the combination with "forceSalted" may lock
321  // him out from frontend
322  if ($extConf['forceSalted']) {
323  $this->setErrorLevel('warning');
324  $problems[] = nl2br($lang->getLL('ext.saltedpasswords.configuration.message.infoForceSalted')) .
325  '<strong><i>' . $lang->getLL('ext.saltedpasswords.configuration.label.important') .
326  '</i></strong> ' . $lang->getLL('ext.saltedpasswords.configuration.message.warningForceSaltedNoteForFrontend');
327  } else {
328  // Inform the user that things like openid won't work anymore
329  $this->setErrorLevel('info');
330  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.infoOnlyFrontendAuthService');
331  }
332  }
333  // forceSalted is set
334  if ($extConf['forceSalted'] && !$extConf['onlyAuthService']) {
335  $this->setErrorLevel('warning');
336  $problems[] = nl2br($lang->getLL('ext.saltedpasswords.configuration.message.infoForceSalted')) .
337  '<strong><i>' . $lang->getLL('ext.saltedpasswords.configuration.label.important') .
338  '</i></strong> ' . $lang->getLL('ext.saltedpasswords.configuration.message.warningForceSaltedNote2');
339  }
340  // updatePasswd wont work with "forceSalted"
341  if ($extConf['updatePasswd'] && $extConf['forceSalted']) {
342  $this->setErrorLevel('error');
343  $problems[] = nl2br($lang->getLL('ext.saltedpasswords.configuration.message.errorForceSaltedAndUpdatePassword'));
344  }
345  } else {
346  // Not enabled warning
347  $this->setErrorLevel('info');
348  $problems[] = $lang->getLL('ext.saltedpasswords.configuration.message.infoSaltedpasswordsFrontendDisabled');
349  }
350  $this->problems = $problems;
351  $result = $this->renderMessage();
352  if (!empty($params['propertyName'])) {
353  return $result['html'];
354  }
355  return $result;
356  }
357 
366  protected function buildHashMethodSelector(array $params, $pObj, $disposal)
367  {
368  $this->init();
369  $propertyName = $params['propertyName'];
370  $unknownVariablePleaseRenameMe = '\'' . substr(md5($propertyName), 0, 10) . '\'';
371  $pField = '';
373  foreach ($registeredMethods as $class => $reference) {
374  $classInstance = GeneralUtility::getUserObj($reference);
375  if ($classInstance instanceof \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface && $classInstance->isAvailable()) {
376  $sel = $this->extConf[$disposal]['saltedPWHashingMethod'] == $class ? ' selected="selected" ' : '';
377  $label = 'ext.saltedpasswords.title.' . strtolower(end(explode('\\', $class)));
378  $pField .= '<option value="' . htmlspecialchars($class) . '"' . $sel . '>' . $GLOBALS['LANG']->getLL($label) . '</option>';
379  }
380  }
381  $pField = '<select id="' . $propertyName . '" name="' . $params['fieldName'] .
382  '" onChange="uFormUrl(' . $unknownVariablePleaseRenameMe . ')">' . $pField . '</select>';
383  return $pField;
384  }
385 
394  public function buildHashMethodSelectorFE(array $params, $pObj)
395  {
396  return $this->buildHashMethodSelector($params, $pObj, 'FE');
397  }
398 
407  public function buildHashMethodSelectorBE(array $params, $pObj)
408  {
409  return $this->buildHashMethodSelector($params, $pObj, 'BE');
410  }
411 
419  protected function processPostData(array $postArray = [])
420  {
421  foreach ($postArray as $key => $value) {
422  // @todo Explain
423  $parts = explode('.', $key, 2);
424  if (count($parts) == 2) {
425  // @todo Explain
426  $value = $this->processPostData([$parts[1] => $value]);
427  $postArray[$parts[0] . '.'] = array_merge((array)$postArray[$parts[0] . '.'], $value);
428  } else {
429  // @todo Explain
430  $postArray[$parts[0]] = $value;
431  }
432  }
433  return $postArray;
434  }
435 
439  protected function getLanguageService()
440  {
441  return $GLOBALS['LANG'];
442  }
443 }
static getSaltingInstance($saltedHash= '', $mode=TYPO3_MODE)
Definition: SaltFactory.php:83
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)