Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 32ec288

Browse filesBrowse files
committed
[HttpFoundation] refactored Request exceptions
1 parent d876809 commit 32ec288
Copy full SHA for 32ec288

File tree

11 files changed

+86
-26
lines changed
Filter options

11 files changed

+86
-26
lines changed

‎src/Symfony/Component/Debug/Exception/FlattenException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Debug/Exception/FlattenException.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace Symfony\Component\Debug\Exception;
1313

14-
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
14+
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
1515
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
1616

1717
/**
@@ -42,7 +42,7 @@ public static function create(\Exception $exception, $statusCode = null, array $
4242
if ($exception instanceof HttpExceptionInterface) {
4343
$statusCode = $exception->getStatusCode();
4444
$headers = array_merge($headers, $exception->getHeaders());
45-
} elseif ($exception instanceof SuspiciousOperationException) {
45+
} elseif ($exception instanceof RequestExceptionInterface) {
4646
$statusCode = 400;
4747
}
4848

‎src/Symfony/Component/HttpFoundation/Exception/ConflictingHeadersException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Exception/ConflictingHeadersException.php
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@
1414
/**
1515
* The HTTP request contains headers with conflicting information.
1616
*
17-
* This exception should trigger an HTTP 400 response in your application code.
18-
*
1917
* @author Magnus Nordlander <magnus@fervo.se>
2018
*/
21-
class ConflictingHeadersException extends \RuntimeException
19+
class ConflictingHeadersException extends \UnexpectedValueException implements RequestExceptionInterface
2220
{
2321
}
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation\Exception;
13+
14+
/**
15+
* Interface for Request exceptions.
16+
*
17+
* Exceptions implementing this interface should trigger an HTTP 400 response in the application code.
18+
*/
19+
interface RequestExceptionInterface
20+
{
21+
}

‎src/Symfony/Component/HttpFoundation/Exception/SuspiciousOperationException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Exception/SuspiciousOperationException.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
* Raised when a user has performed an operation that should be considered
1616
* suspicious from a security perspective.
1717
*/
18-
class SuspiciousOperationException extends \UnexpectedValueException
18+
class SuspiciousOperationException extends \UnexpectedValueException implements RequestExceptionInterface
1919
{
2020
}

‎src/Symfony/Component/HttpFoundation/Request.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Request.php
+22-4Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ class Request
207207

208208
protected static $requestFactory;
209209

210+
private $isHostValid = true;
211+
private $isClientIpsValid = true;
212+
210213
/**
211214
* Constructor.
212215
*
@@ -820,7 +823,12 @@ public function getClientIps()
820823
}
821824

822825
if ($hasTrustedForwardedHeader && $hasTrustedClientIpHeader && $forwardedClientIps !== $xForwardedForClientIps) {
823-
throw new ConflictingHeadersException('The request has both a trusted Forwarded header and a trusted Client IP header, conflicting with each other with regards to the originating IP addresses of the request. This is the result of a misconfiguration. You should either configure your proxy only to send one of these headers, or configure Symfony to distrust one of them.');
826+
if (!$this->isClientIpsValid) {
827+
return array('0.0.0.0');
828+
}
829+
$this->isClientIpsValid = false;
830+
831+
throw new ConflictingHeadersException('The request has both a trusted Forwarded header and a trusted Client IP header, conflicting with each other with regards to the originating IP addresses of the request. This is the result of a misconfiguration. You should either configure your proxy only to send one of these headers, or configure your project to distrust one of them.');
824832
}
825833

826834
if (!$hasTrustedForwardedHeader && !$hasTrustedClientIpHeader) {
@@ -1199,7 +1207,7 @@ public function isSecure()
11991207
*
12001208
* @return string
12011209
*
1202-
* @throws SuspiciousOperationException when the host name is invalid
1210+
* @throws SuspiciousOperationException when the host name is invalid or not trusted
12031211
*/
12041212
public function getHost()
12051213
{
@@ -1221,7 +1229,12 @@ public function getHost()
12211229
// check that it does not contain forbidden characters (see RFC 952 and RFC 2181)
12221230
// use preg_replace() instead of preg_match() to prevent DoS attacks with long host names
12231231
if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) {
1224-
throw new SuspiciousOperationException(sprintf('Invalid Host "%s"', $host));
1232+
if (!$this->isHostValid) {
1233+
return '';
1234+
}
1235+
$this->isHostValid = false;
1236+
1237+
throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host));
12251238
}
12261239

12271240
if (count(self::$trustedHostPatterns) > 0) {
@@ -1239,7 +1252,12 @@ public function getHost()
12391252
}
12401253
}
12411254

1242-
throw new SuspiciousOperationException(sprintf('Untrusted Host "%s"', $host));
1255+
if (!$this->isHostValid) {
1256+
return '';
1257+
}
1258+
$this->isHostValid = false;
1259+
1260+
throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host));
12431261
}
12441262

12451263
return $host;

‎src/Symfony/Component/HttpFoundation/Tests/RequestTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1873,7 +1873,7 @@ public function testTrustedHosts()
18731873
$request->getHost();
18741874
$this->fail('Request::getHost() should throw an exception when host is not trusted.');
18751875
} catch (SuspiciousOperationException $e) {
1876-
$this->assertEquals('Untrusted Host "evil.com"', $e->getMessage());
1876+
$this->assertEquals('Untrusted Host "evil.com".', $e->getMessage());
18771877
}
18781878

18791879
// trusted hosts

‎src/Symfony/Component/HttpKernel/EventListener/RouterListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
+1-6Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Symfony\Component\HttpKernel\EventListener;
1313

1414
use Psr\Log\LoggerInterface;
15-
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
1615
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
1716
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
1817
use Symfony\Component\HttpKernel\KernelEvents;
@@ -69,11 +68,7 @@ public function __construct($matcher, RequestStack $requestStack, RequestContext
6968
private function setCurrentRequest(Request $request = null)
7069
{
7170
if (null !== $request) {
72-
try {
73-
$this->context->fromRequest($request);
74-
} catch (SuspiciousOperationException $e) {
75-
// Do nothing.
76-
}
71+
$this->context->fromRequest($request);
7772
}
7873
}
7974

‎src/Symfony/Component/HttpKernel/EventListener/ValidateRequestListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/EventListener/ValidateRequestListener.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
use Symfony\Component\HttpKernel\KernelEvents;
1717

1818
/**
19-
* Validates that the headers and other information indicating the
20-
* client IP address of a request are consistent.
19+
* Validates Requests.
2120
*
2221
* @author Magnus Nordlander <magnus@fervo.se>
2322
*/
@@ -36,9 +35,10 @@ public function onKernelRequest(GetResponseEvent $event)
3635
$request = $event->getRequest();
3736

3837
if ($request::getTrustedProxies()) {
39-
// This will throw an exception if the headers are inconsistent.
4038
$request->getClientIps();
4139
}
40+
41+
$request->getHost();
4242
}
4343

4444
/**

‎src/Symfony/Component/HttpKernel/HttpKernel.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/HttpKernel.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
2626
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
2727
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
28-
use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
28+
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
2929
use Symfony\Component\HttpFoundation\Request;
3030
use Symfony\Component\HttpFoundation\RequestStack;
3131
use Symfony\Component\HttpFoundation\Response;
@@ -67,8 +67,8 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
6767
try {
6868
return $this->handleRaw($request, $type);
6969
} catch (\Exception $e) {
70-
if ($e instanceof ConflictingHeadersException) {
71-
$e = new BadRequestHttpException('The request headers contain conflicting information regarding the origin of this request.', $e);
70+
if ($e instanceof RequestExceptionInterface) {
71+
$e = new BadRequestHttpException($e->getMessage(), $e);
7272
}
7373
if (false === $catch) {
7474
$this->finishRequest($request, $type);

‎src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php
+30-2Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Component\HttpKernel\Tests\EventListener;
13-
12+
use Symfony\Component\EventDispatcher\EventDispatcher;
1413
use Symfony\Component\HttpFoundation\Request;
14+
use Symfony\Component\HttpFoundation\RequestStack;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
17+
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
18+
use Symfony\Component\HttpKernel\EventListener\ExceptionListener;
1519
use Symfony\Component\HttpKernel\EventListener\RouterListener;
20+
use Symfony\Component\HttpKernel\EventListener\ValidateRequestListener;
1621
use Symfony\Component\HttpKernel\HttpKernelInterface;
22+
use Symfony\Component\HttpKernel\HttpKernel;
1723
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
1824
use Symfony\Component\Routing\RequestContext;
1925

@@ -154,4 +160,26 @@ public function getLoggingParameterData()
154160
array(array(), 'Matched route "{route}".', array('route' => 'n/a', 'route_parameters' => array(), 'request_uri' => 'http://localhost/', 'method' => 'GET')),
155161
);
156162
}
163+
164+
public function testWithBadRequest()
165+
{
166+
$requestStack = new RequestStack();
167+
168+
$requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
169+
$requestMatcher->expects($this->never())->method('matchRequest');
170+
171+
$dispatcher = new EventDispatcher();
172+
$dispatcher->addSubscriber(new ValidateRequestListener());
173+
$dispatcher->addSubscriber(new RouterListener($requestMatcher, $requestStack, new RequestContext()));
174+
$dispatcher->addSubscriber(new ExceptionListener(function () {
175+
return new Response('Exception handled', 400);
176+
}));
177+
178+
$kernel = new HttpKernel($dispatcher, new ControllerResolver(), $requestStack, new ArgumentResolver());
179+
180+
$request = Request::create('http://localhost/');
181+
$request->headers->set('host', '###');
182+
$response = $kernel->handle($request);
183+
$this->assertSame(400, $response->getStatusCode());
184+
}
157185
}

‎src/Symfony/Component/HttpKernel/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/composer.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php": ">=5.5.9",
2020
"symfony/event-dispatcher": "~2.8|~3.0",
21-
"symfony/http-foundation": "~2.8.13|~3.1.6|~3.2",
21+
"symfony/http-foundation": "~3.3",
2222
"symfony/debug": "~2.8|~3.0",
2323
"psr/log": "~1.0"
2424
},

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.