Commit 485af2b6 authored by Benni Mack's avatar Benni Mack
Browse files

[FEATURE] Introduce ModifyFileDumpEvent

A new PSR-14 based event "ModifyFileDumpEvent" is
introduced in favor of the existing
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess']
hook, which is now marked as deprecated, along with
its interface "FileDumpEIDHookInterface".

In contrast to the hook, the new event also contains
the PSR-7 Request and additionally allows to replace
the file, being dumped.

Resolves: #95080
Releases: master
Change-Id: Idbb0f2f38678c12e752e2255aa71853362f8cc46
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70865

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Wouter Wolters's avatarWouter Wolters <typo3@wouterwolters.nl>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Wouter Wolters's avatarWouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent e6e789e6
......@@ -17,10 +17,12 @@ declare(strict_types=1);
namespace TYPO3\CMS\Core\Controller;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Http\Response;
use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
use TYPO3\CMS\Core\Resource\Event\ModifyFileDumpEvent;
use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\FileInterface;
......@@ -37,14 +39,18 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
*/
class FileDumpController
{
/**
* @var ResourceFactory
*/
protected $resourceFactory;
protected ResourceFactory $resourceFactory;
protected EventDispatcherInterface $eventDispatcher;
protected ResponseFactoryInterface $responseFactory;
public function __construct(ResourceFactory $resourceFactory)
{
public function __construct(
EventDispatcherInterface $eventDispatcher,
ResourceFactory $resourceFactory,
ResponseFactoryInterface $responseFactory
) {
$this->eventDispatcher = $eventDispatcher;
$this->resourceFactory = $resourceFactory;
$this->responseFactory = $responseFactory;
}
/**
......@@ -62,14 +68,22 @@ class FileDumpController
$parameters = $this->buildParametersFromRequest($request);
if (!$this->isTokenValid($parameters, $request)) {
return (new Response())->withStatus(403);
return $this->responseFactory->createResponse(403);
}
$file = $this->createFileObjectByParameters($parameters);
if ($file === null) {
return (new Response())->withStatus(404);
return $this->responseFactory->createResponse(404);
}
if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'])) {
trigger_error(
'The hook $TYPO3_CONF_VARS[SC_OPTIONS][FileDumpEID.php][checkFileAccess] is deprecated and will stop working in TYPO3 v12.0. Use the ModifyFileDumpEvent instead.',
E_USER_DEPRECATED
);
}
// Hook: allow some other process to do some security/access checks. Hook should return 403 response if access is rejected, void otherwise
// @deprecated: will be removed in TYPO3 v12.0.
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess'] ?? [] as $className) {
$hookObject = GeneralUtility::makeInstance($className);
if (!$hookObject instanceof FileDumpEIDHookInterface) {
......@@ -81,6 +95,15 @@ class FileDumpController
}
}
// Allow some other process to do some security/access checks.
// Event Listeners should return a 403 response if access is rejected
$event = new ModifyFileDumpEvent($file, $request);
$event = $this->eventDispatcher->dispatch($event);
if ($event->isPropagationStopped()) {
return $event->getResponse();
}
$file = $event->getFile();
$processingInstructions = [];
// Apply cropping, if possible
......
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Resource\Event;
use Psr\EventDispatcher\StoppableEventInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Resource\ResourceInterface;
/**
* Event that is triggered when a file should be dumped to the browser, allowing to perform custom
* security/access checks when accessing a file through a direct link, and returning an alternative
* Response.
*
* It is also possible to replace the file during this event, but not setting a response.
*
* As soon as a custom Response is added, the propagation is stopped.
*/
final class ModifyFileDumpEvent implements StoppableEventInterface
{
private ResourceInterface $file;
private ServerRequestInterface $request;
private ?ResponseInterface $response = null;
public function __construct(ResourceInterface $file, ServerRequestInterface $request)
{
$this->file = $file;
$this->request = $request;
}
public function getFile(): ResourceInterface
{
return $this->file;
}
public function setFile(ResourceInterface $file): void
{
$this->file = $file;
}
public function getRequest(): ServerRequestInterface
{
return $this->request;
}
public function setResponse(ResponseInterface $response): void
{
$this->response = $response;
}
public function getResponse(): ?ResponseInterface
{
return $this->response;
}
public function isPropagationStopped(): bool
{
return $this->response !== null;
}
}
......@@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Resource\ResourceInterface;
/**
* Interface for FileDumpEID Hook to perform some custom security/access checks
* when accessing file thought FileDumpEID
* @deprecated since TYPO3 v11 LTS, will be removed in TYPO3 v12.0. Use the PSR-14-based ModifyFileDumpEvent instead.
*/
interface FileDumpEIDHookInterface
{
......
.. include:: ../../Includes.txt
===================================================
Deprecation: #95077 - FileDump CheckFileAccess hook
===================================================
See :issue:`95077`
Description
===========
The TYPO3 Hook :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess']`
which is executed in the :php:`FileDumpConroller` class, enabiling third-party
code to perfom additional access / security checks before dumping the requested
file, has been deprecated.
The accompanied PHP Interface for the hook
:php:`TYPO3\CMS\Core\Resource\Hook\FileDumpEIDHookInterface` has been marked
as deprecated as well.
Impact
======
If a hook is registered in a TYPO3 installation, a PHP deprecation
message is triggered. The extension scanner also detects any usage
of the deprecated interface as strong, and the definition of the
hook as weak match.
Affected Installations
======================
TYPO3 installations with custom extensions using this hook.
Migration
=========
Migrate to the newly introduced `ModifyFileDumpEvent` PSR-14 event.
.. index:: PHP-API, FullyScanned, ext:core
.. include:: ../../Includes.txt
================================================
Feature: #95077 - New PSR-14 ModifyFileDumpEvent
================================================
See :issue:`95077`
Description
===========
A new PSR-14 event `ModifyFileDumpEvent` has been added to TYPO3 Core.
This event is fired in the :php:`FileDumpController` and allows extensions
to perfom additional access / security checks before dumping a file. The
event does not only contain the file to dump but also the PSR-7 Request.
In case the file dump should be rejected, the event has to set a PSR-7
Response, usually with a `403` status code. This will then immediately
stop the propagation.
With the new event, it's not only possbile to reject the file dump request,
but also to replace the file, which should be dumped.
Registration of the Event in your extensions' `Services.yaml`:
.. code-block:: yaml
MyVendor\MyPackage\Resource\MyEventListener:
tags:
- name: event.listener
identifier: 'my-package/resource/my-event-listener'
The corresponding event listener class:
.. code-block:: php
use TYPO3\CMS\Core\Resource\Event\ModifyFileDumpEvent;
class MyEventListener {
public function __invoke(ModifyFileDumpEvent $event): void
{
// do magic here
}
}
Impact
======
This event can be used to modify the file dump request, by either
adding an alternative response or by replacing the file being dumped.
.. index:: PHP-API, ext:core
......@@ -507,4 +507,9 @@ return [
'Deprecation-95077-FilelistEditIconsHook.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'FileDumpEID.php\'][\'checkFileAccess\']' => [
'restFiles' => [
'Deprecation-95080-FileDumpCheckFileAccessHook.rst',
],
],
];
......@@ -1794,4 +1794,9 @@ return [
'Deprecation-95077-FilelistEditIconsHook.rst',
],
],
'TYPO3\CMS\Core\Resource\Hook\FileDumpEIDHookInterface' => [
'restFiles' => [
'Deprecation-95080-FileDumpCheckFileAccessHook.rst',
],
],
];
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment