Commit 22c3bfb5 authored by Tino Goratsch's avatar Tino Goratsch

Merge branch 'release/v4.4.3'

parents 54a6b15c a39362b6
......@@ -7,12 +7,12 @@
namespace ACP3\Core\Application;
use ACP3\Core\Application\BootstrapCache\Event\Listener\UserContextSubscriber;
use ACP3\Core\Session\SessionHandlerInterface;
use ACP3\Core\View\Renderer\Smarty\Filters\MoveToBottom;
use FOS\HttpCache\SymfonyCache\EventDispatchingHttpCache;
use FOS\HttpCache\SymfonyCache\PurgeSubscriber;
use FOS\HttpCache\SymfonyCache\RefreshSubscriber;
use FOS\HttpCache\SymfonyCache\UserContextSubscriber;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpCache\StoreInterface;
......
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Application\BootstrapCache\Event\Listener;
use ACP3\Modules\ACP3\Users\Model\AuthenticationModel;
use FOS\HttpCache\SymfonyCache\CacheEvent;
use FOS\HttpCache\SymfonyCache\Events;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Class UserContextSubscriber
* @package ACP3\Core\Application\BootstrapCache\Event\Listener
* @see \FOS\HttpCache\SymfonyCache\UserContextSubscriber for the original file as we had to override some logic...
*/
class UserContextSubscriber implements EventSubscriberInterface
{
/**
* The options configured in the constructor argument or default values.
*
* @var array
*/
private $options;
/**
* Generated user hash.
*
* @var string
*/
private $userHash;
/**
* When creating this subscriber, you can configure a number of options.
*
* - anonymous_hash: Hash used for anonymous user.
* - user_hash_accept_header: Accept header value to be used to request the user hash to the
* backend application. Must match the setup of the backend application.
* - user_hash_header: Name of the header the user context hash will be stored into. Must
* match the setup for the Vary header in the backend application.
* - user_hash_uri: Target URI used in the request for user context hash generation.
* - user_hash_method: HTTP Method used with the hash lookup request for user context hash generation.
* - session_name_prefix: Prefix for session cookies. Must match your PHP session configuration.
*
* @param array $options Options to overwrite the default options
*
* @throws \InvalidArgumentException if unknown keys are found in $options
*/
public function __construct(array $options = [])
{
$resolver = new OptionsResolver();
$resolver->setDefaults([
'anonymous_hash' => '38015b703d82206ebc01d17a39c727e5',
'user_hash_accept_header' => 'application/vnd.fos.user-context-hash',
'user_hash_header' => 'X-User-Context-Hash',
'user_hash_uri' => '/_fos_user_context_hash',
'user_hash_method' => 'GET',
'session_name_prefix' => 'PHPSESSID',
]);
$this->options = $resolver->resolve($options);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
Events::PRE_HANDLE => 'preHandle',
];
}
/**
* Look at the request before it is handled by the kernel.
*
* Adds the user hash header to the request.
*
* Checks if an external request tries tampering with the user context hash mechanism
* to prevent attacks.
*
* @param CacheEvent $event
*/
public function preHandle(CacheEvent $event)
{
$request = $event->getRequest();
if (!$this->isInternalRequest($request)) {
// Prevent tampering attacks on the hash mechanism
if ($request->headers->get('accept') === $this->options['user_hash_accept_header']
|| $request->headers->get($this->options['user_hash_header']) !== null
) {
$event->setResponse(new Response('', 400));
return;
}
if ($request->isMethodSafe()) {
$request->headers->set(
$this->options['user_hash_header'],
$this->getUserHash($event->getKernel(), $request)
);
}
}
// let the kernel handle this request.
}
/**
* Remove unneeded things from the request for user hash generation.
*
* Cleans cookies header to only keep the session identifier cookie, so the hash lookup request
* can be cached per session.
*
* @param Request $hashLookupRequest
* @param Request $originalRequest
*/
protected function cleanupHashLookupRequest(Request $hashLookupRequest, Request $originalRequest)
{
$authCookie = $originalRequest->cookies->get(AuthenticationModel::AUTH_NAME);
if ($authCookie !== null) {
$hashLookupRequest->cookies->set(AuthenticationModel::AUTH_NAME, $authCookie);
}
$sessionIds = array();
foreach ($originalRequest->cookies as $name => $value) {
if ($this->isSessionName($name)) {
$sessionIds[$name] = $value;
$hashLookupRequest->cookies->set($name, $value);
}
}
if (count($sessionIds) > 0) {
$hashLookupRequest->headers->set('Cookie', http_build_query($sessionIds, '', '; '));
}
}
/**
* Checks if passed request object is to be considered internal (e.g. for user hash lookup).
*
* @param Request $request
*
* @return bool
*/
private function isInternalRequest(Request $request)
{
return $request->attributes->get('internalRequest', false) === true;
}
/**
* Returns the user context hash for $request.
*
* @param HttpKernelInterface $kernel
* @param Request $request
* @return string
*/
private function getUserHash(HttpKernelInterface $kernel, Request $request)
{
if (isset($this->userHash)) {
return $this->userHash;
}
if ($this->isAnonymous($request)) {
return $this->userHash = $this->options['anonymous_hash'];
}
// Hash lookup request to let the backend generate the user hash
$hashLookupRequest = $this->generateHashLookupRequest($request);
$resp = $kernel->handle($hashLookupRequest);
// Store the user hash in memory for sub-requests (processed in the same thread).
$this->userHash = $resp->headers->get($this->options['user_hash_header']);
return $this->userHash;
}
/**
* Checks if current request is considered anonymous.
*
* @param Request $request
*
* @return bool
*/
private function isAnonymous(Request $request)
{
// You might have to enable rewriting of the Authorization header in your server config or .htaccess:
// RewriteEngine On
// RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
if ($request->server->has('AUTHORIZATION') ||
$request->server->has('HTTP_AUTHORIZATION') ||
$request->server->has('PHP_AUTH_USER')
) {
return false;
}
if ($request->cookies->has(AuthenticationModel::AUTH_NAME)) {
return false;
}
foreach ($request->cookies as $name => $value) {
if ($this->isSessionName($name)) {
return false;
}
}
return true;
}
/**
* Checks if passed string can be considered as a session name, such as would be used in cookies.
*
* @param string $name
*
* @return bool
*/
private function isSessionName($name)
{
return strpos($name, $this->options['session_name_prefix']) === 0;
}
/**
* Generates the request object that will be forwarded to get the user context hash.
*
* @param Request $request
*
* @return Request The request that will return the user context hash value.
*/
private function generateHashLookupRequest(Request $request)
{
$hashLookupRequest = Request::create(
$this->options['user_hash_uri'],
$this->options['user_hash_method'],
[],
[],
[],
$request->server->all()
);
$hashLookupRequest->attributes->set('internalRequest', true);
$hashLookupRequest->headers->set('Accept', $this->options['user_hash_accept_header']);
$this->cleanupHashLookupRequest($hashLookupRequest, $request);
return $hashLookupRequest;
}
}
......@@ -14,7 +14,7 @@ interface BootstrapInterface extends HttpKernelInterface
/**
* Contains the current ACP3 version string
*/
const VERSION = '4.4.2';
const VERSION = '4.4.3';
/**
* Performs some startup checks
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"suggest": {
"acp3/module-seo": "Provides additional SEO capabilities"
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"suggest": {
"acp3/module-captcha": "Provides basic protection against spam bots."
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"suggest": {
"acp3/module-captcha": "Provides basic protection against spam bots."
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,11 +17,11 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2",
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3",
"mibe/feedwriter": "^1.0"
},
"autoload": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,13 +17,13 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2",
"acp3/module-categories": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3",
"acp3/module-categories": "^4.4.3"
},
"suggest": {
"acp3/module-seo": "Provides additional SEO capabilities"
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"suggest": {
"acp3/module-seo": "Provides additional SEO capabilities"
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"suggest": {
"acp3/module-captcha": "Provides basic protection against spam bots."
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,13 +17,13 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2",
"acp3/module-categories": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3",
"acp3/module-categories": "^4.4.3"
},
"suggest": {
"acp3/module-seo": "Provides additional SEO capabilities"
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"suggest": {
"acp3/module-captcha": "Provides basic protection against spam bots."
......
......@@ -17,11 +17,11 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-system": "^4.4.2",
"acp3/module-users": "^4.4.2",
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-system": "^4.4.3",
"acp3/module-users": "^4.4.3",
"thepixeldeveloper/sitemap": "^4.4.2"
},
"autoload": {
......
......@@ -18,11 +18,11 @@
"require": {
"composer/semver": "^1.4",
"acp3/composer-installer": "*",
"acp3/core": "^4.4.2",
"acp3/setup": "^4.4.2",
"acp3/module-errors": "^4.4.2",
"acp3/module-permissions": "^4.4.2",
"acp3/module-users": "^4.4.2"
"acp3/core": "^4.4.3",
"acp3/setup": "^4.4.3",
"acp3/module-errors": "^4.4.3",
"acp3/module-permissions": "^4.4.3",
"acp3/module-users": "^4.4.3"
},