From 5ec92e8af35d36facf52db9cfecd3fde7a1d06fa Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 30 Jun 2016 08:29:00 +0200 Subject: [PATCH 1/3] [travis] Fix deps=low/high patching --- .travis.php => .github/travis.php | 10 +++++++--- .travis.yml | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) rename .travis.php => .github/travis.php (83%) diff --git a/.travis.php b/.github/travis.php similarity index 83% rename from .travis.php rename to .github/travis.php index 7618c272e8..9470836ef5 100644 --- a/.travis.php +++ b/.github/travis.php @@ -1,19 +1,23 @@ $_SERVER['argc']) { - echo "Usage: branch dir1 dir2 ... dirN\n"; + echo "Usage: branch version dir1 dir2 ... dirN\n"; exit(1); } $dirs = $_SERVER['argv']; array_shift($dirs); $branch = array_shift($dirs); +$version = array_shift($dirs); $packages = array(); $flags = PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0; foreach ($dirs as $dir) { - if (!`git diff --name-only $branch...HEAD -- $dir`) { + if (!system("git diff --name-only $branch...HEAD -- $dir", $exitStatus)) { + if ($exitStatus) { + exit($exitStatus); + } continue; } echo "$dir\n"; @@ -32,7 +36,7 @@ foreach ($dirs as $dir) { file_put_contents($dir.'/composer.json', $json); passthru("cd $dir && tar -cf package.tar --exclude='package.tar' *"); - $package->version = $branch.'.x-dev'; + $package->version = $version.'.x-dev'; $package->dist['type'] = 'tar'; $package->dist['url'] = 'file://'.__DIR__."/$dir/package.tar"; diff --git a/.travis.yml b/.travis.yml index b5a28f71fb..76e38fcb1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,7 +64,7 @@ before_install: install: - if [[ ! $skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi # Create local composer packages for each patched components and reference them in composer.json files when cross-testing components - - if [[ ! $skip && $deps ]]; then php .travis.php $TRAVIS_BRANCH $COMPONENTS; fi + - if [[ ! $skip && $deps ]]; then git fetch origin $TRAVIS_BRANCH && php .github/travis.php FETCH_HEAD $TRAVIS_BRANCH $COMPONENTS; fi # For the master branch when deps=high, the version before master is checked out and tested with the locally patched components - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then SYMFONY_VERSION=$(git ls-remote --heads | grep -o '/[1-9].*' | tail -n 1 | sed s/.//); else SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*'); fi - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then git fetch origin $SYMFONY_VERSION; git checkout -m FETCH_HEAD; COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); ./phpunit install; fi From 1f00b553735f47f7614d98968cfdf2eb2f9c0b48 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 29 Jun 2016 19:50:09 +0200 Subject: [PATCH 2/3] [HttpKernel] Move conflicting origin IPs handling to catch block --- .../Component/HttpKernel/HttpKernel.php | 10 +++------- .../HttpKernel/Tests/HttpKernelTest.php | 20 +++++++------------ 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 2b8146127e..4e628a1409 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -63,6 +63,9 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface 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); @@ -115,13 +118,6 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface */ 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 diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 59c1d33425..372c2a3c1b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -276,7 +276,13 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase */ public function testInconsistentClientIpsOnMasterRequests() { - $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver()); + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::REQUEST, function ($event) { + $event->getRequest()->getClientIp(); + }); + + $kernel = new HttpKernel($dispatcher, $this->getResolver()); + $request = new Request(); $request->setTrustedProxies(array('1.1.1.1')); $request->server->set('REMOTE_ADDR', '1.1.1.1'); @@ -286,18 +292,6 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase $kernel->handle($request, $kernel::MASTER_REQUEST, false); } - public function testInconsistentClientIpsOnSubRequests() - { - $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver()); - $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'); - - $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $kernel->handle($request, $kernel::SUB_REQUEST, false)); - } - protected function getResolver($controller = null) { if (null === $controller) { From db841018dce300566c15a959bd6add7aaab7b831 Mon Sep 17 00:00:00 2001 From: Magnus Nordlander Date: Mon, 2 May 2016 14:34:55 +0200 Subject: [PATCH 3/3] [HttpKernel] Add listener that checks when request has both Forwarded and X-Forwarded-For --- .../FrameworkBundle/Resources/config/web.xml | 4 ++ .../Bundle/FrameworkBundle/composer.json | 4 +- .../EventListener/ValidateRequestListener.php | 55 +++++++++++++++++++ .../ValidateRequestListenerTest.php | 42 ++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/EventListener/ValidateRequestListener.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml index 9b2f3cb3a4..c1f73e5610 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml @@ -46,5 +46,9 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index bcfce7b707..9f62cb42e7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -22,8 +22,8 @@ "symfony/config": "~2.4", "symfony/event-dispatcher": "~2.5", "symfony/finder": "~2.0,>=2.0.5", - "symfony/http-foundation": "~2.4.9|~2.5,>=2.5.4", - "symfony/http-kernel": "~2.7", + "symfony/http-foundation": "~2.7", + "symfony/http-kernel": "~2.7.15|~2.8.8", "symfony/filesystem": "~2.3", "symfony/routing": "~2.6,>2.6.4", "symfony/security-core": "~2.6.13|~2.7.9|~2.8", diff --git a/src/Symfony/Component/HttpKernel/EventListener/ValidateRequestListener.php b/src/Symfony/Component/HttpKernel/EventListener/ValidateRequestListener.php new file mode 100644 index 0000000000..00096ccf9e --- /dev/null +++ b/src/Symfony/Component/HttpKernel/EventListener/ValidateRequestListener.php @@ -0,0 +1,55 @@ + + * + * 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 + */ +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), + ), + ); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php new file mode 100644 index 0000000000..842a3869cb --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ValidateRequestListenerTest.php @@ -0,0 +1,42 @@ + + * + * 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); + } +}