From 9054cdfdcc498a1ad7dae77d9cdc12f6ca425566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Somogyi=20M=C3=A1rton?= Date: Sat, 5 Oct 2019 21:33:29 +0200 Subject: [PATCH] Fixes #17521: Request::getUserHost() and request::getUserIp() (#17593) --- framework/web/Request.php | 38 +++++++++++++++++------------ tests/framework/web/RequestTest.php | 37 ++++++++++++++++------------ 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/framework/web/Request.php b/framework/web/Request.php index 88a1a1271b..9d1215d3d4 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -291,7 +291,7 @@ class Request extends \yii\base\Request */ protected function filterHeaders(HeaderCollection $headerCollection) { - $trustedHeaders = $this->getTrustedIpHeaders(); + $trustedHeaders = $this->getTrustedHeaders(); // remove all secure headers unless they are trusted foreach ($this->secureHeaders as $secureHeader) { @@ -302,11 +302,11 @@ class Request extends \yii\base\Request } /** - * Trusted Ip headers according to the [[trustedHosts]]. + * Trusted headers according to the [[trustedHosts]]. * @return array * @since 2.0.28 */ - protected function getTrustedIpHeaders() + protected function getTrustedHeaders() { // do not trust any of the [[secureHeaders]] by default $trustedHeaders = []; @@ -1136,13 +1136,13 @@ class Request extends \yii\base\Request } /** - * Returns the user IP address. - * The IP is determined using headers and / or `$_SERVER` variables. + * Returns the user IP address from [[ipHeaders]]. * @return string|null user IP address, null if not available + * @see $ipHeaders + * @since 2.0.28 */ - public function getUserIP() - { - foreach($this->getTrustedIpHeaders() as $ipHeader) { + protected function getUserIpFromIpHeaders() { + foreach($this->ipHeaders as $ipHeader) { if ($this->headers->has($ipHeader)) { $ip = $this->getUserIpFromIpHeader($this->headers->get($ipHeader)); if ($ip !== null) { @@ -1150,8 +1150,18 @@ class Request extends \yii\base\Request } } } + return null; + } - return $this->getRemoteIP(); + /** + * Returns the user IP address. + * The IP is determined using headers and / or `$_SERVER` variables. + * @return string|null user IP address, null if not available + */ + public function getUserIP() + { + $ip = $this->getUserIpFromIpHeaders(); + return $ip === null ? $this->getRemoteIP() : $ip; } /** @@ -1205,13 +1215,11 @@ class Request extends \yii\base\Request */ public function getUserHost() { - foreach ($this->ipHeaders as $ipHeader) { - if ($this->headers->has($ipHeader)) { - return gethostbyaddr(trim(explode(',', $this->headers->get($ipHeader))[0])); - } + $userIp = $this->getUserIpFromIpHeaders(); + if($userIp === null) { + return $this->getRemoteHost(); } - - return $this->getRemoteHost(); + return gethostbyaddr($userIp); } /** diff --git a/tests/framework/web/RequestTest.php b/tests/framework/web/RequestTest.php index 3082b9544f..ed9a7b819e 100644 --- a/tests/framework/web/RequestTest.php +++ b/tests/framework/web/RequestTest.php @@ -728,32 +728,37 @@ class RequestTest extends TestCase public function trustedHostAndInjectedXForwardedForDataProvider() { return [ - 'emptyIPs' => ['1.1.1.1', '', ['10.10.10.10'], '1.1.1.1'], - 'invalidIp' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, apple', ['10.10.10.10'], '1.1.1.1'], - 'invalidIp2' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, 300.300.300.300', ['10.10.10.10'], '1.1.1.1'], - 'invalidIp3' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, 10.0.0.0/26', ['10.0.0.0/24'], '1.1.1.1'], - 'invalidLatestIp' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, apple, 2.2.2.2', ['1.1.1.1', '2.2.2.2'], '2.2.2.2'], - 'notTrusted' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', ['10.10.10.10'], '1.1.1.1'], - 'trustedLevel1' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', ['1.1.1.1'], '2.2.2.2'], - 'trustedLevel2' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', ['1.1.1.1', '2.2.2.2'], '8.8.8.8'], - 'trustedLevel3' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', ['1.1.1.1', '2.2.2.2', '8.8.8.8'], '127.0.0.1'], - 'trustedLevel4' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', ['1.1.1.1', '2.2.2.2', '8.8.8.8', '127.0.0.1'], '127.0.0.1'], - 'trustedLevel4EmptyElements' => ['1.1.1.1', '127.0.0.1, 8.8.8.8,,,, , , 2.2.2.2', ['1.1.1.1', '2.2.2.2', '8.8.8.8', '127.0.0.1'], '127.0.0.1'], - 'trustedWithCidr' => ['10.0.0.2', '127.0.0.1, 8.8.8.8, 10.0.0.240, 10.0.0.32, 10.0.0.99', ['10.0.0.0/24'], '8.8.8.8'], - 'trustedAll' => ['10.0.0.2', '127.0.0.1, 8.8.8.8, 10.0.0.240, 10.0.0.32, 10.0.0.99', ['0.0.0.0/0'], '127.0.0.1'], + 'emptyIPs' => ['1.1.1.1', '', null, ['10.10.10.10'], '1.1.1.1'], + 'invalidIp' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, apple', null, ['10.10.10.10'], '1.1.1.1'], + 'invalidIp2' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, 300.300.300.300', null, ['10.10.10.10'], '1.1.1.1'], + 'invalidIp3' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, 10.0.0.0/26', null, ['10.0.0.0/24'], '1.1.1.1'], + 'invalidLatestIp' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2, apple, 2.2.2.2', null, ['1.1.1.1', '2.2.2.2'], '2.2.2.2'], + 'notTrusted' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', null, ['10.10.10.10'], '1.1.1.1'], + 'trustedLevel1' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', null, ['1.1.1.1'], '2.2.2.2'], + 'trustedLevel2' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', null, ['1.1.1.1', '2.2.2.2'], '8.8.8.8'], + 'trustedLevel3' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', null, ['1.1.1.1', '2.2.2.2', '8.8.8.8'], '127.0.0.1'], + 'trustedLevel4' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', null, ['1.1.1.1', '2.2.2.2', '8.8.8.8', '127.0.0.1'], '127.0.0.1'], + 'trustedLevel4EmptyElements' => ['1.1.1.1', '127.0.0.1, 8.8.8.8,,,, , , 2.2.2.2', null, ['1.1.1.1', '2.2.2.2', '8.8.8.8', '127.0.0.1'], '127.0.0.1'], + 'trustedWithCidr' => ['10.0.0.2', '127.0.0.1, 8.8.8.8, 10.0.0.240, 10.0.0.32, 10.0.0.99', null, ['10.0.0.0/24'], '8.8.8.8'], + 'trustedAll' => ['10.0.0.2', '127.0.0.1, 8.8.8.8, 10.0.0.240, 10.0.0.32, 10.0.0.99', null, ['0.0.0.0/0'], '127.0.0.1'], + 'emptyIpHeaders' => ['1.1.1.1', '127.0.0.1, 8.8.8.8, 2.2.2.2', [], ['1.1.1.1'], '1.1.1.1'], ]; } /** * @dataProvider trustedHostAndInjectedXForwardedForDataProvider */ - public function testTrustedHostAndInjectedXForwardedFor($remoteAddress, $xForwardedFor, $trustedHosts, $expectedUserIp) + public function testTrustedHostAndInjectedXForwardedFor($remoteAddress, $xForwardedFor, $ipHeaders, $trustedHosts, $expectedUserIp) { $_SERVER['REMOTE_ADDR'] = $remoteAddress; $_SERVER['HTTP_X_FORWARDED_FOR'] = $xForwardedFor; - $request = new Request([ + $params = [ 'trustedHosts' => $trustedHosts, - ]); + ]; + if($ipHeaders !== null) { + $params['ipHeaders'] = $ipHeaders; + } + $request = new Request($params); $this->assertSame($expectedUserIp, $request->getUserIP()); }