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