‪TYPO3CMS  ‪main
PolicyProvider.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\EventDispatcher\EventDispatcherInterface;
21 use Psr\Http\Message\ServerRequestInterface;
22 use Psr\Http\Message\UriInterface;
30 
36 final class ‪PolicyProvider
37 {
38  protected const ‪REPORTING_URI = '@http-reporting';
39 
40  public function ‪__construct(
41  private readonly ‪RequestId $requestId,
42  private readonly ‪SiteFinder $siteFinder,
43  private readonly ‪PolicyRegistry $policyRegistry,
44  private readonly EventDispatcherInterface $eventDispatcher,
45  protected readonly ‪MutationRepository $mutationRepository,
46  ) {}
47 
51  public function ‪provideFor(‪Scope $scope): ‪Policy
52  {
53  // @todo add policy cache per scope
54  $defaultPolicy = new ‪Policy();
55  $mutationCollections = iterator_to_array(
56  $this->mutationRepository->findByScope($scope),
57  false
58  );
59  // add temporary(!) mutations that were collected during processing this request
60  if ($this->policyRegistry->hasMutationCollections()) {
61  $mutationCollections = array_merge(
62  $mutationCollections,
63  $this->policyRegistry->getMutationCollections()
64  );
65  }
66  // apply all mutations to current policy
67  $currentPolicy = $defaultPolicy->mutate(...$mutationCollections);
68  // allow other components to modify the current policy individually via PSR-14 event
69  $event = new ‪PolicyMutatedEvent($scope, $defaultPolicy, $currentPolicy, ...$mutationCollections);
70  $this->eventDispatcher->dispatch($event);
71  return $event->getCurrentPolicy();
72  }
73 
74  public function ‪getReportingUrlFor(‪Scope $scope, ServerRequestInterface $request): ?UriInterface
75  {
76  $value = ‪$GLOBALS['TYPO3_CONF_VARS'][$scope->type->abbreviate()]['contentSecurityPolicyReportingUrl'] ?? null;
77  if (!empty($value) && is_string($value)) {
78  try {
79  return new ‪Uri($value);
80  } catch (\InvalidArgumentException) {
81  return null;
82  }
83  }
84  $uriBase = $this->‪getDefaultReportingUriBase($scope, $request);
85  return $uriBase->withQuery($uriBase->getQuery() . '&requestTime=' . $this->requestId->microtime);
86  }
87 
91  public function ‪getDefaultReportingUriBase(‪Scope $scope, ServerRequestInterface $request, bool $absolute = true): UriInterface
92  {
93  $normalizedParams = $request->getAttribute('normalizedParams') ?? ‪NormalizedParams::createFromRequest($request);
94  // resolve URI from current site language or site default language in frontend scope
95  if ($scope->‪isFrontendSite()) {
96  $site = $this->‪resolveSite($scope);
97  $siteLanguage = $request->getAttribute('siteLanguage');
98  $siteLanguage = $siteLanguage instanceof ‪SiteLanguage ? $siteLanguage : $site->getDefaultLanguage();
99  $uri = $siteLanguage->‪getBase();
100  $uri = $uri->withPath(rtrim($uri->getPath(), '/') . '/');
101  // otherwise fall back to current request URI
102  } else {
103  $uri = new ‪Uri($normalizedParams->getSitePath());
104  }
105  // add `typo3/` path in backend scope
106  if ($scope->type->isBackend()) {
107  $uri = $uri->withPath($uri->getPath() . 'typo3/');
108  }
109  // prefix current require scheme, host, port in case it's not given
110  if ($absolute && ($uri->getScheme() === '' || $uri->getHost() === '')) {
111  $current = new ‪Uri($normalizedParams->getSiteUrl());
112  $uri = $uri
113  ->withScheme($current->getScheme())
114  ->withHost($current->getHost())
115  ->withPort($current->getPort());
116  } elseif (!$absolute && $uri->getScheme() !== '' && $uri->getHost() !== '') {
117  $uri = $uri->withScheme('')->withHost('')->withPort(null);
118  }
119  // `/en/@http-reporting?csp=report` (relative)
120  // `https://ip12.anyhost.it:8443/en/@http-reporting?csp=report` (absolute)
121  return $uri->withPath($uri->getPath() . self::REPORTING_URI)->withQuery('csp=report');
122  }
123 
124  private function ‪resolveSite(‪Scope $scope): ‪Site
125  {
126  return $scope->site ?? $this->siteFinder->getSiteByIdentifier($scope->siteIdentifier);
127  }
128 }
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyRegistry
Definition: PolicyRegistry.php:28
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\Policy
Definition: Policy.php:31
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:30
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:27
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\getBase
‪getBase()
Definition: SiteLanguage.php:179
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\Event\PolicyMutatedEvent
Definition: PolicyMutatedEvent.php:26
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider\REPORTING_URI
‪const REPORTING_URI
Definition: PolicyProvider.php:38
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\MutationRepository
Definition: MutationRepository.php:29
‪TYPO3\CMS\Core\Core\RequestId
Definition: RequestId.php:26
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider\getReportingUrlFor
‪getReportingUrlFor(Scope $scope, ServerRequestInterface $request)
Definition: PolicyProvider.php:74
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\Scope
Definition: Scope.php:30
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy
Definition: ConsumableNonce.php:18
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider\__construct
‪__construct(private readonly RequestId $requestId, private readonly SiteFinder $siteFinder, private readonly PolicyRegistry $policyRegistry, private readonly EventDispatcherInterface $eventDispatcher, protected readonly MutationRepository $mutationRepository,)
Definition: PolicyProvider.php:40
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\Scope\isFrontendSite
‪isFrontendSite()
Definition: Scope.php:126
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider\getDefaultReportingUriBase
‪getDefaultReportingUriBase(Scope $scope, ServerRequestInterface $request, bool $absolute=true)
Definition: PolicyProvider.php:91
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider\provideFor
‪provideFor(Scope $scope)
Definition: PolicyProvider.php:51
‪TYPO3\CMS\Core\Http\NormalizedParams\createFromRequest
‪static static createFromRequest(ServerRequestInterface $request, array $systemConfiguration=null)
Definition: NormalizedParams.php:840
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider
Definition: PolicyProvider.php:37
‪TYPO3\CMS\Core\Http\NormalizedParams
Definition: NormalizedParams.php:38
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider\resolveSite
‪resolveSite(Scope $scope)
Definition: PolicyProvider.php:124