‪TYPO3CMS  9.5
BackendModuleController.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
34 
46 {
47  private const ‪FLAG_CONFIRMATION_REQUEST = 1;
48  protected const ‪FLAG_INSTALL_TOOL_PASSWORD = 2;
49  private const ‪ALLOWED_ACTIONS = ['maintenance', 'settings', 'upgrade', 'environment'];
50 
54  protected ‪$sessionService;
55 
59  protected ‪$uriBuilder;
60 
61  public function ‪__construct()
62  {
63  $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
64  }
65 
73  public function ‪backendUserConfirmationAction(ServerRequestInterface $request): ResponseInterface
74  {
75  $flags = (int)($request->getQueryParams()['flags'] ?? 0);
76  $targetController = (string)($request->getQueryParams()['targetController'] ?? '');
77  $targetHash = (string)($request->getQueryParams()['targetHash'] ?? '');
78  $expectedTargetHash = GeneralUtility::hmac($targetController, BackendModuleController::class);
79  $flagInstallToolPassword = (bool)($flags & self::FLAG_INSTALL_TOOL_PASSWORD);
80  $flagInvalidPassword = false;
81 
82  if (!in_array($targetController, self::ALLOWED_ACTIONS, true)
83  || !hash_equals($expectedTargetHash, $targetHash)) {
84  return new ‪HtmlResponse('', 403);
85  }
86  if ($flags & self::FLAG_CONFIRMATION_REQUEST) {
87  if ($flagInstallToolPassword && $this->‪verifyInstallToolPassword($request)) {
88  return $this->‪setAuthorizedAndRedirect($targetController);
89  }
90  if (!$flagInstallToolPassword && $this->‪verifyBackendUserPassword($request)) {
91  return $this->‪setAuthorizedAndRedirect($targetController);
92  }
93  $flagInvalidPassword = true;
94  }
95 
96  $view = GeneralUtility::makeInstance(StandaloneView::class);
97  $view->getTemplatePaths()->setTemplatePathAndFilename(
99  'install',
100  'Resources/Private/Templates/BackendModule/BackendUserConfirmation.html'
101  )
102  );
103  $view->assignMultiple([
104  'flagInvalidPassword' => $flagInvalidPassword,
105  'flagInstallToolPassword' => $flagInstallToolPassword,
106  'languageFileReference' => 'LLL:EXT:install/Resources/Private/Language/BackendModule.xlf',
107  'passwordModeUri' => $this->‪getBackendUserConfirmationUri([
108  'targetController' => $targetController,
109  'targetHash' => $targetHash,
110  // current flags, unset FLAG_CONFIRMATION_REQUEST, toggle FLAG_INSTALL_TOOL_PASSWORD
111  'flags' => $flags & ~self::FLAG_CONFIRMATION_REQUEST ^ self::FLAG_INSTALL_TOOL_PASSWORD,
112  ]),
113  'verifyUri' => $this->‪getBackendUserConfirmationUri([
114  'targetController' => $targetController,
115  'targetHash' => $targetHash,
116  // current flags, add FLAG_CONFIRMATION_REQUEST
117  'flags' => $flags | self::FLAG_CONFIRMATION_REQUEST,
118  ]),
119  'cancelUri' => '',
120  ]);
121  $this->‪applyRsaAuthModules();
122  return new HtmlResponse($view->render());
123  }
124 
130  public function ‪maintenanceAction(): ResponseInterface
131  {
132  return $this->‪getBackendUserConfirmationRedirect('maintenance')
133  ?? $this->‪setAuthorizedAndRedirect('maintenance');
134  }
135 
141  public function ‪settingsAction(): ResponseInterface
142  {
143  return $this->‪getBackendUserConfirmationRedirect('settings')
144  ?? $this->‪setAuthorizedAndRedirect('settings');
145  }
146 
152  public function ‪upgradeAction(): ResponseInterface
153  {
154  return $this->‪getBackendUserConfirmationRedirect('upgrade')
155  ?? $this->‪setAuthorizedAndRedirect('upgrade');
156  }
157 
163  public function ‪environmentAction(): ResponseInterface
164  {
165  return $this->‪getBackendUserConfirmationRedirect('environment')
166  ?? $this->‪setAuthorizedAndRedirect('environment');
167  }
168 
175  protected function ‪getBackendUserConfirmationRedirect(string $targetController): ?ResponseInterface
176  {
177  if ($this->‪getSessionService()->isAuthorizedBackendUserSession()) {
178  return null;
179  }
180  if (‪Environment::getContext()->isDevelopment()) {
181  return null;
182  }
183  $redirectUri = $this->‪getBackendUserConfirmationUri([
184  'targetController' => $targetController,
185  'targetHash' => GeneralUtility::hmac($targetController, BackendModuleController::class),
186  ]);
187  return new RedirectResponse((string)$redirectUri, 403);
188  }
189 
190  protected function ‪getBackendUserConfirmationUri(array $parameters): ‪Uri
191  {
192  return $this->uriBuilder->buildUriFromRoute(
193  'install.backend-user-confirmation',
194  $parameters
195  );
196  }
197 
205  protected function ‪setAuthorizedAndRedirect(string $controller): ResponseInterface
206  {
208  $redirectLocation = 'install.php?install[controller]=' . $controller . '&install[context]=backend';
209  return new RedirectResponse($redirectLocation, 303);
210  }
211 
218  protected function ‪verifyInstallToolPassword(ServerRequestInterface $request): bool
219  {
220  $parsedBody = $request->getParsedBody();
221  $password = $parsedBody['confirmationPassword'] ?? null;
222  $installToolPassword = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'] ?? null;
223  if (!is_string($password) || empty($installToolPassword)) {
224  return false;
225  }
226 
227  try {
228  $hashFactory = GeneralUtility::makeInstance(PasswordHashFactory::class);
229  $hashInstance = $hashFactory->get($installToolPassword, 'BE');
230  return $hashInstance->checkPassword($password, $installToolPassword);
231  } catch (InvalidPasswordHashException $exception) {
232  return false;
233  }
234  }
235 
243  protected function ‪verifyBackendUserPassword(ServerRequestInterface $request): bool
244  {
245  $parsedBody = $request->getParsedBody();
246  $password = empty($parsedBody['confirmationPasswordInternal'])
247  ? ($parsedBody['confirmationPassword'] ?? null) // default field
248  : $parsedBody['confirmationPasswordInternal']; // filled e.g. by `ext:rsaauth`
249  if (!is_string($password)) {
250  return false;
251  }
252 
253  // clone current backend user object to avoid
254  // possible side effects for the real instance
255  $backendUser = clone $this->‪getBackendUser();
256  $loginData = [
257  'status' => 'sudo-mode',
258  'origin' => BackendModuleController::class,
259  'uname' => $backendUser->user['username'],
260  'uident' => $password,
261  ];
262  // currently there is no dedicated API to perform authentication
263  // that's why this process partially has to be simulated here
264  $loginData = $backendUser->‪processLoginData($loginData);
265  $authInfo = $backendUser->‪getAuthInfoArray();
266 
267  $authenticated = false;
269  foreach ($this->getAuthServices($backendUser, $loginData, $authInfo) as ‪$service) {
270  $ret = (int)‪$service->authUser($backendUser->user);
271  if ($ret <= 0) {
272  return false;
273  }
274  if ($ret >= 200) {
275  return true;
276  }
277  if ($ret >= 100) {
278  continue;
279  }
280  $authenticated = true;
281  continue;
282  }
283  return $authenticated;
284  }
285 
294  protected function getAuthServices(BackendUserAuthentication $backendUser, array $loginData, array $authInfo): \Generator
295  {
296  $serviceChain = [];
297  $subType = 'authUserBE';
298  while (‪$service = GeneralUtility::makeInstanceService('auth', $subType, $serviceChain)) {
299  $serviceChain[] = ‪$service->getServiceKey();
300  if (!is_object(‪$service)) {
301  break;
302  }
303  ‪$service->initAuth($subType, $loginData, $authInfo, $backendUser);
304  yield ‪$service;
305  }
306  }
307 
308  protected function ‪getBackendUser(): ‪BackendUserAuthentication
309  {
310  return ‪$GLOBALS['BE_USER'];
311  }
312 
319  protected function ‪getSessionService(): SessionService
320  {
321  if ($this->sessionService === null) {
322  $this->sessionService = new SessionService();
323  $this->sessionService->startSession();
324  }
326  }
327 
328  protected function ‪applyRsaAuthModules()
329  {
330  if (!‪ExtensionManagementUtility::isLoaded('rsaauth')) {
331  return;
332  }
333  $rsaEncryptionEncoder = GeneralUtility::makeInstance(RsaEncryptionEncoder::class);
334  $rsaEncryptionEncoder->enableRsaEncryption(true);
335  }
336 }
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:25
‪TYPO3\CMS\Install\Controller\BackendModuleController\ALLOWED_ACTIONS
‪const ALLOWED_ACTIONS
Definition: BackendModuleController.php:49
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\processLoginData
‪array processLoginData($loginData, $passwordTransmissionStrategy='')
Definition: AbstractUserAuthentication.php:1336
‪TYPO3\CMS\Install\Controller\BackendModuleController\getBackendUserConfirmationUri
‪getBackendUserConfirmationUri(array $parameters)
Definition: BackendModuleController.php:188
‪TYPO3\CMS\Install\Controller\BackendModuleController\verifyBackendUserPassword
‪bool verifyBackendUserPassword(ServerRequestInterface $request)
Definition: BackendModuleController.php:241
‪TYPO3\CMS\Install\Controller\BackendModuleController\maintenanceAction
‪ResponseInterface maintenanceAction()
Definition: BackendModuleController.php:128
‪TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException
Definition: InvalidPasswordHashException.php:22
‪TYPO3\CMS\Install\Controller\BackendModuleController\$uriBuilder
‪UriBuilder $uriBuilder
Definition: BackendModuleController.php:57
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getAuthInfoArray
‪array getAuthInfoArray()
Definition: AbstractUserAuthentication.php:1401
‪TYPO3\CMS\Core\Authentication\AbstractAuthenticationService
Definition: AbstractAuthenticationService.php:27
‪TYPO3\CMS\Install\Controller\BackendModuleController\upgradeAction
‪ResponseInterface upgradeAction()
Definition: BackendModuleController.php:150
‪TYPO3\CMS\Install\Service\SessionService\setAuthorizedBackendSession
‪setAuthorizedBackendSession()
Definition: SessionService.php:272
‪TYPO3\CMS\Install\Controller\BackendModuleController\settingsAction
‪ResponseInterface settingsAction()
Definition: BackendModuleController.php:139
‪TYPO3\CMS\Install\Controller\BackendModuleController\getBackendUser
‪getBackendUser()
Definition: BackendModuleController.php:306
‪TYPO3\CMS\Install\Controller\BackendModuleController\backendUserConfirmationAction
‪ResponseInterface backendUserConfirmationAction(ServerRequestInterface $request)
Definition: BackendModuleController.php:71
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:27
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static ApplicationContext getContext()
Definition: Environment.php:106
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:36
‪TYPO3\CMS\Install\Controller\BackendModuleController\getSessionService
‪SessionService getSessionService()
Definition: BackendModuleController.php:317
‪TYPO3\CMS\Install\Controller\BackendModuleController\FLAG_CONFIRMATION_REQUEST
‪const FLAG_CONFIRMATION_REQUEST
Definition: BackendModuleController.php:47
‪TYPO3\CMS\Install\Controller\BackendModuleController\applyRsaAuthModules
‪applyRsaAuthModules()
Definition: BackendModuleController.php:326
‪TYPO3\CMS\Install\Controller
Definition: AbstractController.php:3
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:35
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key, $exitOnError=null)
Definition: ExtensionManagementUtility.php:115
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Rsaauth\RsaEncryptionEncoder
Definition: RsaEncryptionEncoder.php:29
‪TYPO3\CMS\Install\Controller\BackendModuleController\verifyInstallToolPassword
‪bool verifyInstallToolPassword(ServerRequestInterface $request)
Definition: BackendModuleController.php:216
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:27
‪TYPO3\CMS\Install\Controller\BackendModuleController\getBackendUserConfirmationRedirect
‪ResponseInterface null getBackendUserConfirmationRedirect(string $targetController)
Definition: BackendModuleController.php:173
‪TYPO3\CMS\Install\Controller\BackendModuleController\__construct
‪__construct()
Definition: BackendModuleController.php:59
‪TYPO3\CMS\Install\Controller\BackendModuleController\$service
‪yield $service
Definition: BackendModuleController.php:302
‪TYPO3\CMS\Install\Controller\BackendModuleController\FLAG_INSTALL_TOOL_PASSWORD
‪const FLAG_INSTALL_TOOL_PASSWORD
Definition: BackendModuleController.php:48
‪TYPO3\CMS\Install\Controller\BackendModuleController\$sessionService
‪SessionService $sessionService
Definition: BackendModuleController.php:53
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:32
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:149
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Install\Controller\BackendModuleController\environmentAction
‪ResponseInterface environmentAction()
Definition: BackendModuleController.php:161
‪TYPO3\CMS\Install\Controller\BackendModuleController\setAuthorizedAndRedirect
‪ResponseInterface setAuthorizedAndRedirect(string $controller)
Definition: BackendModuleController.php:203
‪TYPO3\CMS\Install\Service\SessionService
Definition: SessionService.php:30
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:25
‪TYPO3\CMS\Install\Controller\BackendModuleController
Definition: BackendModuleController.php:46