‪TYPO3CMS  10.4
Maintenance.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\Container\ContainerInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
23 use Psr\Http\Server\MiddlewareInterface;
24 use Psr\Http\Server\RequestHandlerInterface;
25 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
48 use TYPO3\CMS\Install\Service\SessionService;
49 
55 class ‪Maintenance implements MiddlewareInterface
56 {
60  protected ‪$packageManager;
61 
65  protected ‪$configurationManager;
66 
70  protected ‪$passwordHashFactory;
71 
75  private ‪$container;
76 
80  protected ‪$controllers = [
81  'icon' => IconController::class,
82  'layout' => LayoutController::class,
83  'login' => LoginController::class,
84  'maintenance' => MaintenanceController::class,
85  'settings' => SettingsController::class,
86  'upgrade' => UpgradeController::class,
87  'environment' => EnvironmentController::class,
88  ];
89 
90  public function ‪__construct(
92  ConfigurationManager ‪$configurationManager,
94  ContainerInterface ‪$container
95  ) {
96  $this->packageManager = ‪$packageManager;
97  $this->configurationManager = ‪$configurationManager;
98  $this->passwordHashFactory = ‪$passwordHashFactory;
99  $this->container = ‪$container;
100  }
101 
109  public function ‪process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
110  {
111  if (!$this->‪canHandleRequest($request)) {
112  return $handler->handle($request);
113  }
114 
115  $controllerName = $request->getQueryParams()['install']['controller'] ?? 'layout';
116  $actionName = $request->getParsedBody()['install']['action'] ?? $request->getQueryParams()['install']['action'] ?? 'init';
117 
118  if ($actionName === 'showEnableInstallToolFile' && ‪EnableFileService::isInstallToolEnableFilePermanent()) {
119  $actionName = 'showLogin';
120  }
121 
122  $action = $actionName . 'Action';
123 
124  // not session related actions
125  if ($actionName === 'init') {
126  $controller = $this->container->get(LayoutController::class);
127  return $controller->initAction($request);
128  }
129  if ($actionName === 'checkEnableInstallToolFile') {
130  return new JsonResponse([
131  'success' => $this->‪checkEnableInstallToolFile(),
132  ]);
133  }
134  if ($actionName === 'showEnableInstallToolFile') {
135  $controller = $this->container->get(LoginController::class);
136  return $controller->showEnableInstallToolFileAction($request);
137  }
138  if ($actionName === 'showLogin') {
139  if (!$this->‪checkEnableInstallToolFile()) {
140  throw new \RuntimeException('Not authorized', 1505564888);
141  }
142  $controller = $this->container->get(LoginController::class);
143  return $controller->showLoginAction($request);
144  }
145 
146  // session related actions
147  $session = new SessionService();
148 
149  // the backend user has an active session but the admin / maintainer
150  // rights have been revoked or the user was disabled or deleted in the meantime
151  if ($session->isAuthorizedBackendUserSession() && !$session->hasActiveBackendUserRoleAndSession()) {
152  // log out the user and destroy the session
153  $session->resetSession();
154  $session->destroySession();
155  $formProtection = ‪FormProtectionFactory::get(
156  InstallToolFormProtection::class
157  );
158  $formProtection->clean();
159 
160  return new HtmlResponse('', 403);
161  }
162 
163  if ($actionName === 'preAccessCheck') {
164  $response = new JsonResponse([
165  'installToolLocked' => !$this->‪checkEnableInstallToolFile(),
166  'isAuthorized' => $session->isAuthorized()
167  ]);
168  } elseif ($actionName === 'checkLogin') {
169  if (!$this->‪checkEnableInstallToolFile() && !$session->isAuthorizedBackendUserSession()) {
170  throw new \RuntimeException('Not authorized', 1505563556);
171  }
172  if ($session->isAuthorized()) {
173  $session->refreshSession();
174  $response = new JsonResponse([
175  'success' => true,
176  ]);
177  } else {
178  // Session expired, log out user, start new session
179  $session->resetSession();
180  $session->startSession();
181  $response = new JsonResponse([
182  'success' => false,
183  ]);
184  }
185  } elseif ($actionName === 'login') {
186  $session->initializeSession();
187  if (!$this->‪checkEnableInstallToolFile()) {
188  throw new \RuntimeException('Not authorized', 1505567462);
189  }
190  $this->‪checkSessionToken($request, $session);
191  $this->‪checkSessionLifetime($session);
192  $password = $request->getParsedBody()['install']['password'] ?? null;
193  $authService = new AuthenticationService($session);
194  if ($authService->loginWithPassword($password, $request)) {
195  $response = new JsonResponse([
196  'success' => true,
197  ]);
198  } else {
199  if ($password === null || empty($password)) {
200  $messageQueue = (new FlashMessageQueue('install'))->enqueue(
201  new FlashMessage('Please enter the install tool password', '', ‪FlashMessage::ERROR)
202  );
203  } else {
204  $hashInstance = $this->passwordHashFactory->getDefaultHashInstance('BE');
205  $hashedPassword = $hashInstance->getHashedPassword($password);
206  $messageQueue = (new FlashMessageQueue('install'))->enqueue(
207  new FlashMessage(
208  'Given password does not match the install tool login password. Calculated hash: ' . $hashedPassword,
209  '',
211  )
212  );
213  }
214  $response = new JsonResponse([
215  'success' => false,
216  'status' => $messageQueue,
217  ]);
218  }
219  } elseif ($actionName === 'logout') {
222  }
223  $formProtection = ‪FormProtectionFactory::get(
224  InstallToolFormProtection::class
225  );
226  $formProtection->clean();
227  $session->destroySession();
228  $response = new JsonResponse([
229  'success' => true,
230  ]);
231  } else {
232  $enforceReferrerResponse = $this->‪enforceReferrer($request);
233  if ($enforceReferrerResponse instanceof ResponseInterface) {
234  return $enforceReferrerResponse;
235  }
236  $session->initializeSession();
237  if (
238  !$this->‪checkSessionToken($request, $session)
239  || !$this->‪checkSessionLifetime($session)
240  || !$session->isAuthorized()
241  ) {
242  return new HtmlResponse('', 403);
243  }
244  $session->refreshSession();
245  if (!array_key_exists($controllerName, $this->controllers)) {
246  throw new \RuntimeException(
247  'Unknown controller ' . $controllerName,
248  1505215756
249  );
250  }
252  $className = $this->controllers[$controllerName];
254  $controller = $this->container->get($className);
255  if (!method_exists($controller, $action)) {
256  throw new \RuntimeException(
257  'Unknown action method ' . $action . ' in controller ' . $controllerName,
258  1505216027
259  );
260  }
261  $response = $controller->$action($request);
262  }
263 
264  return $response;
265  }
266 
275  protected function ‪canHandleRequest(ServerRequestInterface $request): bool
276  {
277  $basicIntegrity = $this->‪checkIfEssentialConfigurationExists()
278  && !empty(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'])
280  if (!$basicIntegrity) {
281  return false;
282  }
283  return true;
284  }
285 
291  protected function ‪checkEnableInstallToolFile()
292  {
294  }
295 
303  protected function ‪checkSessionToken(ServerRequestInterface $request, SessionService $session): bool
304  {
305  $postValues = $request->getParsedBody()['install'];
306  // no post data is there, so no token check necessary
307  if (empty($postValues)) {
308  return true;
309  }
310  $tokenOk = false;
311  // A token must be given as soon as there is POST data
312  if (isset($postValues['token'])) {
313  $formProtection = ‪FormProtectionFactory::get(
314  InstallToolFormProtection::class
315  );
316  $action = (string)$postValues['action'];
317  if ($action === '') {
318  throw new \RuntimeException(
319  'No POST action given for token check',
320  1369326593
321  );
322  }
323  $tokenOk = $formProtection->validateToken($postValues['token'], 'installTool', $action);
324  }
325  if (!$tokenOk) {
326  $session->resetSession();
327  $session->startSession();
328  }
329  return $tokenOk;
330  }
331 
339  protected function ‪checkSessionLifetime(SessionService $session): bool
340  {
341  $isExpired = $session->isExpired();
342  if ($isExpired) {
343  // Session expired, log out user, start new session
344  $session->resetSession();
345  $session->startSession();
346  }
347  return !$isExpired;
348  }
349 
355  protected function ‪checkIfEssentialConfigurationExists(): bool
356  {
357  return file_exists($this->configurationManager->getLocalConfigurationFileLocation());
358  }
359 
366  protected function ‪recreatePackageStatesFileIfMissing(): void
367  {
368  if (!file_exists(‪Environment::getLegacyConfigPath() . '/PackageStates.php')) {
369  $packages = $this->packageManager->getAvailablePackages();
370  foreach ($packages as $package) {
371  if ($package instanceof PackageInterface && $package->isPartOfMinimalUsableSystem()) {
372  $this->packageManager->activatePackage($package->getPackageKey());
373  }
374  }
375  $this->packageManager->forceSortAndSavePackageStates();
376  }
377  }
378 
387  protected function ‪enforceReferrer(ServerRequestInterface $request): ?ResponseInterface
388  {
389  if (!(new Features())->isFeatureEnabled('security.backend.enforceReferrer')) {
390  return null;
391  }
392  return (new ReferrerEnforcer($request))->handle([
393  'flags' => ['refresh-always'],
394  'subject' => 'Install Tool',
395  ]);
396  }
397 }
‪TYPO3\CMS\Core\Http\Security\ReferrerEnforcer
Definition: ReferrerEnforcer.php:31
‪TYPO3\CMS\Install\Middleware\Maintenance\checkSessionLifetime
‪bool checkSessionLifetime(SessionService $session)
Definition: Maintenance.php:334
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:27
‪TYPO3\CMS\Core\Package\PackageInterface\isPartOfMinimalUsableSystem
‪bool isPartOfMinimalUsableSystem()
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\get
‪static TYPO3 CMS Core FormProtection AbstractFormProtection get($classNameOrType='default',... $constructorArguments)
Definition: FormProtectionFactory.php:74
‪TYPO3\CMS\Install\Middleware\Maintenance\$configurationManager
‪ConfigurationManager $configurationManager
Definition: Maintenance.php:63
‪TYPO3\CMS\Core\Package\FailsafePackageManager
Definition: FailsafePackageManager.php:26
‪TYPO3\CMS\Install\Middleware\Maintenance
Definition: Maintenance.php:56
‪TYPO3\CMS\Install\Middleware\Maintenance\recreatePackageStatesFileIfMissing
‪recreatePackageStatesFileIfMissing()
Definition: Maintenance.php:361
‪TYPO3\CMS\Install\Controller\UpgradeController
Definition: UpgradeController.php:80
‪TYPO3\CMS\Install\Controller\EnvironmentController
Definition: EnvironmentController.php:53
‪TYPO3\CMS\Install\Service\EnableFileService
Definition: EnableFileService.php:26
‪TYPO3\CMS\Install\Middleware\Maintenance\canHandleRequest
‪bool canHandleRequest(ServerRequestInterface $request)
Definition: Maintenance.php:270
‪TYPO3\CMS\Install\Controller\IconController
Definition: IconController.php:32
‪TYPO3\CMS\Core\Package\PackageInterface
Definition: PackageInterface.php:22
‪TYPO3\CMS\Core\FormProtection\InstallToolFormProtection
Definition: InstallToolFormProtection.php:61
‪TYPO3\CMS\Install\Service\EnableFileService\checkInstallToolEnableFile
‪static bool checkInstallToolEnableFile()
Definition: EnableFileService.php:112
‪TYPO3\CMS\Install\Service\EnableFileService\removeInstallToolEnableFile
‪static bool removeInstallToolEnableFile()
Definition: EnableFileService.php:77
‪TYPO3\CMS\Install\Service\EnableFileService\installToolEnableFileExists
‪static bool installToolEnableFileExists()
Definition: EnableFileService.php:102
‪TYPO3\CMS\Install\Middleware\Maintenance\$packageManager
‪FailsafePackageManager $packageManager
Definition: Maintenance.php:59
‪TYPO3\CMS\Install\Controller\LoginController
Definition: LoginController.php:32
‪TYPO3\CMS\Core\Configuration\Features
Definition: Features.php:56
‪TYPO3\CMS\Install\Middleware\Maintenance\$container
‪ContainerInterface $container
Definition: Maintenance.php:71
‪TYPO3\CMS\Install\Service\EnableFileService\isInstallToolEnableFilePermanent
‪static bool isInstallToolEnableFilePermanent()
Definition: EnableFileService.php:132
‪TYPO3\CMS\Install\Service\EnableFileService\isFirstInstallAllowed
‪static bool isFirstInstallAllowed()
Definition: EnableFileService.php:45
‪TYPO3\CMS\Install\Middleware\Maintenance\$controllers
‪array $controllers
Definition: Maintenance.php:75
‪TYPO3\CMS\Install\Controller\LayoutController
Definition: LayoutController.php:39
‪TYPO3\CMS\Install\Middleware\Maintenance\$passwordHashFactory
‪PasswordHashFactory $passwordHashFactory
Definition: Maintenance.php:67
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:24
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:47
‪TYPO3\CMS\Core\Http\JsonResponse
Definition: JsonResponse.php:26
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Install\Middleware\Maintenance\process
‪ResponseInterface process(ServerRequestInterface $request, RequestHandlerInterface $handler)
Definition: Maintenance.php:104
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Install\Middleware\Maintenance\checkEnableInstallToolFile
‪bool checkEnableInstallToolFile()
Definition: Maintenance.php:286
‪TYPO3\CMS\Install\Controller\MaintenanceController
Definition: MaintenanceController.php:50
‪TYPO3\CMS\Install\Controller\AbstractController
Definition: AbstractController.php:31
‪TYPO3\CMS\Install\Middleware\Maintenance\checkIfEssentialConfigurationExists
‪bool checkIfEssentialConfigurationExists()
Definition: Maintenance.php:350
‪TYPO3\CMS\Install\Authentication\AuthenticationService
Definition: AuthenticationService.php:39
‪TYPO3\CMS\Install\Controller\SettingsController
Definition: SettingsController.php:48
‪TYPO3\CMS\Install\Middleware\Maintenance\__construct
‪__construct(FailsafePackageManager $packageManager, ConfigurationManager $configurationManager, PasswordHashFactory $passwordHashFactory, ContainerInterface $container)
Definition: Maintenance.php:85
‪TYPO3\CMS\Install\Middleware
Definition: Installer.php:18
‪TYPO3\CMS\Core\Messaging\FlashMessageQueue
Definition: FlashMessageQueue.php:29
‪TYPO3\CMS\Core\Core\Environment\getLegacyConfigPath
‪static string getLegacyConfigPath()
Definition: Environment.php:282
‪TYPO3\CMS\Core\Messaging\AbstractMessage\ERROR
‪const ERROR
Definition: AbstractMessage.php:31
‪TYPO3\CMS\Install\Middleware\Maintenance\checkSessionToken
‪bool checkSessionToken(ServerRequestInterface $request, SessionService $session)
Definition: Maintenance.php:298
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:26
‪TYPO3\CMS\Install\Middleware\Maintenance\enforceReferrer
‪ResponseInterface null enforceReferrer(ServerRequestInterface $request)
Definition: Maintenance.php:382