‪TYPO3CMS  ‪main
BackendModuleController.php
Go to the documentation of this file.
1 <?php
2 
3 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 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
22 use Psr\Http\Message\UriInterface;
34 use TYPO3\CMS\Install\Service\SessionService;
35 
48 {
49  protected const ‪FLAG_CONFIRMATION_REQUEST = 1;
50  protected const ‪FLAG_INSTALL_TOOL_PASSWORD = 2;
51  protected const ‪ALLOWED_ACTIONS = ['maintenance', 'settings', 'upgrade', 'environment'];
52 
53  protected ?SessionService ‪$sessionService = null;
54 
55  public function ‪__construct(
56  protected readonly ‪UriBuilder $uriBuilder,
57  protected readonly ‪ModuleTemplateFactory $moduleTemplateFactory
58  ) {
59  }
60 
65  public function ‪backendUserConfirmationAction(ServerRequestInterface $request): ResponseInterface
66  {
67  $flags = (int)($request->getQueryParams()['flags'] ?? 0);
68  $targetController = (string)($request->getQueryParams()['targetController'] ?? '');
69  $targetHash = (string)($request->getQueryParams()['targetHash'] ?? '');
70  $expectedTargetHash = ‪GeneralUtility::hmac($targetController, BackendModuleController::class);
71  $flagInstallToolPassword = (bool)($flags & self::FLAG_INSTALL_TOOL_PASSWORD);
72  $flagInvalidPassword = false;
73 
74  if (!in_array($targetController, self::ALLOWED_ACTIONS, true)
75  || !hash_equals($expectedTargetHash, $targetHash)) {
76  return new ‪HtmlResponse('', 403);
77  }
78  if ($flags & self::FLAG_CONFIRMATION_REQUEST) {
79  if ($flagInstallToolPassword && $this->‪verifyInstallToolPassword($request)) {
80  return $this->‪setAuthorizedAndRedirect($targetController, $request);
81  }
82  if (!$flagInstallToolPassword && $this->‪verifyBackendUserPassword($request)) {
83  return $this->‪setAuthorizedAndRedirect($targetController, $request);
84  }
85  $flagInvalidPassword = true;
86  }
87 
88  $view = $this->moduleTemplateFactory->create($request);
89  $view->assignMultiple([
90  'flagInvalidPassword' => $flagInvalidPassword,
91  'flagInstallToolPassword' => $flagInstallToolPassword,
92  'passwordModeUri' => $this->‪getBackendUserConfirmationUri([
93  'targetController' => $targetController,
94  'targetHash' => $targetHash,
95  // current flags, unset FLAG_CONFIRMATION_REQUEST, toggle FLAG_INSTALL_TOOL_PASSWORD
96  'flags' => $flags & ~self::FLAG_CONFIRMATION_REQUEST ^ self::FLAG_INSTALL_TOOL_PASSWORD,
97  ]),
98  'verifyUri' => $this->‪getBackendUserConfirmationUri([
99  'targetController' => $targetController,
100  'targetHash' => $targetHash,
101  // current flags, add FLAG_CONFIRMATION_REQUEST
102  'flags' => $flags | self::FLAG_CONFIRMATION_REQUEST,
103  ]),
104  ]);
105 
106  $view->setModuleName('tools_tools' . $targetController);
107  return $view->renderResponse('BackendModule/BackendUserConfirmation');
108  }
109 
113  public function ‪maintenanceAction(ServerRequestInterface $request): ResponseInterface
114  {
115  return $this->‪getBackendUserConfirmationRedirect('maintenance', $request)
116  ?? $this->‪setAuthorizedAndRedirect('maintenance', $request);
117  }
118 
122  public function ‪settingsAction(ServerRequestInterface $request): ResponseInterface
123  {
124  return $this->‪getBackendUserConfirmationRedirect('settings', $request)
125  ?? $this->‪setAuthorizedAndRedirect('settings', $request);
126  }
127 
131  public function ‪upgradeAction(ServerRequestInterface $request): ResponseInterface
132  {
133  return $this->‪getBackendUserConfirmationRedirect('upgrade', $request)
134  ?? $this->‪setAuthorizedAndRedirect('upgrade', $request);
135  }
136 
140  public function ‪environmentAction(ServerRequestInterface $request): ResponseInterface
141  {
142  return $this->‪getBackendUserConfirmationRedirect('environment', $request)
143  ?? $this->‪setAuthorizedAndRedirect('environment', $request);
144  }
145 
149  protected function ‪getBackendUserConfirmationRedirect(string $targetController, ServerRequestInterface $request): ?ResponseInterface
150  {
151  if ($this->‪getSessionService()->isAuthorizedBackendUserSession($request)) {
152  return null;
153  }
154  if (‪Environment::getContext()->isDevelopment()) {
155  return null;
156  }
157  $redirectUri = $this->‪getBackendUserConfirmationUri([
158  'targetController' => $targetController,
159  'targetHash' => ‪GeneralUtility::hmac($targetController, BackendModuleController::class),
160  ]);
161  return new ‪RedirectResponse((string)$redirectUri, 403);
162  }
163 
164  protected function ‪getBackendUserConfirmationUri(array $parameters): UriInterface
165  {
166  return $this->uriBuilder->buildUriFromRoute(
167  'install.backend-user-confirmation',
168  $parameters
169  );
170  }
171 
176  protected function ‪setAuthorizedAndRedirect(string $controller, ServerRequestInterface $request): ResponseInterface
177  {
178  $userSession = $this->‪getBackendUser()->getSession();
179  $this->‪getSessionService()->setAuthorizedBackendSession($userSession);
180  $entryPointResolver = GeneralUtility::makeInstance(BackendEntryPointResolver::class);
181  $redirectLocation = $entryPointResolver->getUriFromRequest($request, 'install.php')->withQuery('?install[controller]=' . $controller . '&install[context]=backend');
182  return new ‪RedirectResponse($redirectLocation, 303);
183  }
184 
188  protected function ‪verifyInstallToolPassword(ServerRequestInterface $request): bool
189  {
190  $parsedBody = $request->getParsedBody();
191  $password = $parsedBody['confirmationPassword'] ?? null;
192  $installToolPassword = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'] ?? null;
193  if (!is_string($password) || empty($installToolPassword)) {
194  return false;
195  }
196 
197  try {
198  $hashFactory = GeneralUtility::makeInstance(PasswordHashFactory::class);
199  $hashInstance = $hashFactory->get($installToolPassword, 'BE');
200  return $hashInstance->checkPassword($password, $installToolPassword);
201  } catch (‪InvalidPasswordHashException $exception) {
202  return false;
203  }
204  }
205 
210  protected function ‪verifyBackendUserPassword(ServerRequestInterface $request): bool
211  {
212  $parsedBody = $request->getParsedBody();
213  $password = $parsedBody['confirmationPassword'] ?? null;
214  if (!is_string($password)) {
215  return false;
216  }
217 
218  // clone current backend user object to avoid
219  // possible side effects for the real instance
220  $backendUser = clone $this->‪getBackendUser();
221  $loginData = [
222  'status' => 'sudo-mode',
223  'origin' => BackendModuleController::class,
224  'uname' => $backendUser->user['username'],
225  'uident' => $password,
226  ];
227  // currently there is no dedicated API to perform authentication
228  // that's why this process partially has to be simulated here
229  ‪$loginData = $backendUser->‪processLoginData(‪$loginData, $request);
230  $authInfo = $backendUser->‪getAuthInfoArray($request);
231 
232  $authenticated = false;
234  foreach ($this->getAuthServices($backendUser, ‪$loginData, $authInfo) as ‪$service) {
235  $ret = (int)‪$service->authUser($backendUser->user);
236  if ($ret <= 0) {
237  return false;
238  }
239  if ($ret >= 200) {
240  return true;
241  }
242  if ($ret < 100) {
243  $authenticated = true;
244  continue;
245  }
246  }
247  return $authenticated;
248  }
249 
255  protected function getAuthServices(‪BackendUserAuthentication $backendUser, array ‪$loginData, array $authInfo): \Generator
256  {
257  $serviceChain = [];
258  $subType = 'authUserBE';
259  while (‪$service = GeneralUtility::makeInstanceService('auth', $subType, $serviceChain)) {
260  $serviceChain[] = ‪$service->getServiceKey();
261  if (!is_object(‪$service)) {
262  break;
263  }
264  ‪$service->initAuth($subType, ‪$loginData, $authInfo, $backendUser);
265  yield ‪$service;
266  }
267  }
268 
270  {
271  return ‪$GLOBALS['BE_USER'];
272  }
273 
278  protected function ‪getSessionService(): SessionService
279  {
280  if ($this->sessionService === null) {
281  $this->sessionService = new SessionService();
282  $this->sessionService->startSession();
283  }
285  }
286 }
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:27
‪TYPO3\CMS\Install\Controller\BackendModuleController\ALLOWED_ACTIONS
‪const ALLOWED_ACTIONS
Definition: BackendModuleController.php:51
‪TYPO3\CMS\Install\Controller\BackendModuleController\backendUserConfirmationAction
‪backendUserConfirmationAction(ServerRequestInterface $request)
Definition: BackendModuleController.php:65
‪TYPO3\CMS\Install\Controller\BackendModuleController\getBackendUserConfirmationUri
‪getBackendUserConfirmationUri(array $parameters)
Definition: BackendModuleController.php:164
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:33
‪TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException
Definition: InvalidPasswordHashException.php:26
‪TYPO3\CMS\Install\Controller\BackendModuleController\settingsAction
‪settingsAction(ServerRequestInterface $request)
Definition: BackendModuleController.php:122
‪TYPO3\CMS\Install\Controller\BackendModuleController\setAuthorizedAndRedirect
‪setAuthorizedAndRedirect(string $controller, ServerRequestInterface $request)
Definition: BackendModuleController.php:176
‪TYPO3\CMS\Core\Authentication\AbstractAuthenticationService
Definition: AbstractAuthenticationService.php:29
‪TYPO3\CMS\Install\Controller\BackendModuleController\getBackendUser
‪getBackendUser()
Definition: BackendModuleController.php:269
‪TYPO3\CMS\Install\Controller\BackendModuleController\upgradeAction
‪upgradeAction(ServerRequestInterface $request)
Definition: BackendModuleController.php:131
‪TYPO3\CMS\Install\Controller\BackendModuleController\maintenanceAction
‪maintenanceAction(ServerRequestInterface $request)
Definition: BackendModuleController.php:113
‪TYPO3\CMS\Install\Controller\BackendModuleController\environmentAction
‪environmentAction(ServerRequestInterface $request)
Definition: BackendModuleController.php:140
‪TYPO3\CMS\Install\Controller\BackendModuleController\getSessionService
‪getSessionService()
Definition: BackendModuleController.php:278
‪TYPO3\CMS\Install\Controller\BackendModuleController\verifyBackendUserPassword
‪verifyBackendUserPassword(ServerRequestInterface $request)
Definition: BackendModuleController.php:210
‪TYPO3\CMS\Webhooks\Message\$loginData
‪identifier readonly UriInterface readonly array $loginData
Definition: LoginErrorOccurredMessage.php:37
‪TYPO3\CMS\Install\Controller\BackendModuleController\FLAG_CONFIRMATION_REQUEST
‪const FLAG_CONFIRMATION_REQUEST
Definition: BackendModuleController.php:49
‪TYPO3\CMS\Install\Controller
Definition: AbstractController.php:18
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:42
‪TYPO3\CMS\Core\Utility\GeneralUtility\hmac
‪static string hmac($input, $additionalSecret='')
Definition: GeneralUtility.php:584
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:66
‪TYPO3\CMS\Install\Controller\BackendModuleController\verifyInstallToolPassword
‪verifyInstallToolPassword(ServerRequestInterface $request)
Definition: BackendModuleController.php:188
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:28
‪TYPO3\CMS\Install\Controller\BackendModuleController\$service
‪yield $service
Definition: BackendModuleController.php:265
‪TYPO3\CMS\Install\Controller\BackendModuleController\FLAG_INSTALL_TOOL_PASSWORD
‪const FLAG_INSTALL_TOOL_PASSWORD
Definition: BackendModuleController.php:50
‪TYPO3\CMS\Install\Controller\BackendModuleController\$sessionService
‪SessionService $sessionService
Definition: BackendModuleController.php:53
‪TYPO3\CMS\Install\Controller\BackendModuleController\__construct
‪__construct(protected readonly UriBuilder $uriBuilder, protected readonly ModuleTemplateFactory $moduleTemplateFactory)
Definition: BackendModuleController.php:55
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getAuthInfoArray
‪array getAuthInfoArray(ServerRequestInterface $request)
Definition: AbstractUserAuthentication.php:1212
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\processLoginData
‪array processLoginData(array $loginData, ServerRequestInterface $request)
Definition: AbstractUserAuthentication.php:1154
‪TYPO3\CMS\Install\Controller\BackendModuleController\getBackendUserConfirmationRedirect
‪getBackendUserConfirmationRedirect(string $targetController, ServerRequestInterface $request)
Definition: BackendModuleController.php:149
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Routing\BackendEntryPointResolver
Definition: BackendEntryPointResolver.php:29
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static getContext()
Definition: Environment.php:128
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:26
‪TYPO3\CMS\Install\Controller\BackendModuleController
Definition: BackendModuleController.php:48