Skip to content

Commit

Permalink
Merge branch '3.0' into 3.1
Browse files Browse the repository at this point in the history
* 3.0:
  [HttpKernel] Add listener that checks when request has both Forwarded and X-Forwarded-For
  [HttpKernel] Move conflicting origin IPs handling to catch block
  [travis] Fix deps=low/high patching
  • Loading branch information
fabpot committed Jun 30, 2016
2 parents 1eed758 + e2a8f77 commit 21da5a7
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 20 deletions.
55 changes: 55 additions & 0 deletions EventListener/ValidateRequestListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
* Validates that the headers and other information indicating the
* client IP address of a request are consistent.
*
* @author Magnus Nordlander <magnus@fervo.se>
*/
class ValidateRequestListener implements EventSubscriberInterface
{
/**
* Performs the validation.
*
* @param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
if (!$event->isMasterRequest()) {
return;
}
$request = $event->getRequest();

if ($request::getTrustedProxies()) {
// This will throw an exception if the headers are inconsistent.
$request->getClientIps();
}
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => array(
array('onKernelRequest', 256),
),
);
}
}
10 changes: 3 additions & 7 deletions HttpKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
try {
return $this->handleRaw($request, $type);
} catch (\Exception $e) {
if ($e instanceof ConflictingHeadersException) {
$e = new BadRequestHttpException('The request headers contain conflicting information regarding the origin of this request.', $e);
}
if (false === $catch) {
$this->finishRequest($request, $type);

Expand Down Expand Up @@ -119,13 +122,6 @@ public function terminateWithException(\Exception $exception)
*/
private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
{
if (self::MASTER_REQUEST === $type && $request::getTrustedProxies()) {
try {
$request->getClientIps();
} catch (ConflictingHeadersException $e) {
throw new BadRequestHttpException('The request headers contain conflicting information regarding the origin of this request.', $e);
}
}
$this->requestStack->push($request);

// request
Expand Down
42 changes: 42 additions & 0 deletions Tests/EventListener/ValidateRequestListenerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel\Tests\EventListener;

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\EventListener\ValidateRequestListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;

class ValidateRequestListenerTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException
*/
public function testListenerThrowsWhenMasterRequestHasInconsistentClientIps()
{
$dispatcher = new EventDispatcher();
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');

$request = new Request();
$request->setTrustedProxies(array('1.1.1.1'));
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$request->headers->set('FORWARDED', '2.2.2.2');
$request->headers->set('X_FORWARDED_FOR', '3.3.3.3');

$dispatcher->addListener(KernelEvents::REQUEST, array(new ValidateRequestListener(), 'onKernelRequest'));
$event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);

$dispatcher->dispatch(KernelEvents::REQUEST, $event);
}
}
19 changes: 6 additions & 13 deletions Tests/HttpKernelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,26 +307,19 @@ public function testVerifyRequestStackPushPopDuringHandle()
*/
public function testInconsistentClientIpsOnMasterRequests()
{
$kernel = $this->getHttpKernel(new EventDispatcher());
$request = new Request();
$request->setTrustedProxies(array('1.1.1.1'));
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$request->headers->set('FORWARDED', '2.2.2.2');
$request->headers->set('X_FORWARDED_FOR', '3.3.3.3');

$kernel->handle($request, $kernel::MASTER_REQUEST, false);
}

public function testInconsistentClientIpsOnSubRequests()
{
$kernel = $this->getHttpKernel(new EventDispatcher());
$request = new Request();
$request->setTrustedProxies(array('1.1.1.1'));
$request->server->set('REMOTE_ADDR', '1.1.1.1');
$request->headers->set('FORWARDED', '2.2.2.2');
$request->headers->set('X_FORWARDED_FOR', '3.3.3.3');
$dispatcher = new EventDispatcher();
$dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
$event->getRequest()->getClientIp();
});

$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $kernel->handle($request, $kernel::SUB_REQUEST, false));
$kernel = $this->getHttpKernel($dispatcher);
$kernel->handle($request, $kernel::MASTER_REQUEST, false);
}

private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = array())
Expand Down

0 comments on commit 21da5a7

Please sign in to comment.