diff --git a/phpBB/phpbb/feed/event/http_auth_subscriber.php b/phpBB/phpbb/feed/event/http_auth_subscriber.php index b2937a3c22..14426f3aad 100644 --- a/phpBB/phpbb/feed/event/http_auth_subscriber.php +++ b/phpBB/phpbb/feed/event/http_auth_subscriber.php @@ -190,6 +190,7 @@ class http_auth_subscriber implements EventSubscriberInterface protected function send_auth_challenge(GetResponseEvent $event) { $realm = $this->config['sitename']; + // Filter out non-ASCII characters per RFC2616 $realm = preg_replace('/[\x80-\xFF]/', '?', $realm); diff --git a/tests/feed/http_auth_subscriber_test.php b/tests/feed/http_auth_subscriber_test.php index ee50ec9088..f25859c535 100644 --- a/tests/feed/http_auth_subscriber_test.php +++ b/tests/feed/http_auth_subscriber_test.php @@ -1,26 +1,33 @@ -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ -namespace phpbb\feed\event; - -class http_auth_subscriber_test extends \phpbb_test_case +class phpbb_feed_http_auth_subscriber_test extends \phpbb_test_case { /** @var \PHPUnit\Framework\MockObject\MockObject|\phpbb\auth\auth */ protected $auth; - /** @var \PHPUnit\Framework\MockObject\MockObject|\phpbb\config\config */ + /** @var \PHPUnit\Framework\MockObject\MockObject|config */ protected $config; + /** @var \PHPUnit\Framework\MockObject\MockObject|\phpbb\language\language */ + protected $language; + /** @var \PHPUnit\Framework\MockObject\MockObject|\phpbb\request\request_interface */ protected $request; @@ -37,12 +44,26 @@ class http_auth_subscriber_test extends \phpbb_test_case $this->auth = $this->getMockBuilder('\phpbb\auth\auth') ->disableOriginalConstructor() ->getMock(); + $this->auth->method('login') + ->willReturnMap([ + ['valid_user', 'valid_password', false, true, false, ['status' => LOGIN_SUCCESS]], + ['invalid_user', 'invalid_password', false, true, false, ['status' => LOGIN_ERROR_USERNAME]], + ['attempts_user', 'valid_password', false, true, false, ['status' => LOGIN_ERROR_ATTEMPTS]], + ]); - $this->config = new \phpbb\config\config(array( + $this->config = new config(array( 'feed_http_auth' => 1, 'sitename' => 'Test Site', )); + $this->language = $this->getMockBuilder('\phpbb\language\language') + ->disableOriginalConstructor() + ->getMock(); + $this->language->method('lang') + ->willReturnMap([ + ['NOT_AUTHORISED', 'NOT_AUTHORISED'], + ]); + $this->request = $this->getMockBuilder('\phpbb\request\request_interface') ->getMock(); @@ -55,6 +76,7 @@ class http_auth_subscriber_test extends \phpbb_test_case $this->subscriber = new http_auth_subscriber( $this->auth, $this->config, + $this->language, $this->request, $this->user ); @@ -140,22 +162,18 @@ class http_auth_subscriber_test extends \phpbb_test_case ->disableOriginalConstructor() ->getMock(); - $request->attributes->expects($this->once()) - ->method('get') - ->with('_route') - ->willReturn('phpbb_feed_overall'); + $request->attributes->expects($this->never()) + ->method('get'); - $request->expects($this->once()) - ->method('isSecure') - ->willReturn(true); + $request->expects($this->never()) + ->method('isSecure'); $event = $this->getMockBuilder('\Symfony\Component\HttpKernel\Event\GetResponseEvent') ->disableOriginalConstructor() ->getMock(); - $event->expects($this->once()) - ->method('getRequest') - ->willReturn($request); + $event->expects($this->never()) + ->method('getRequest'); $event->expects($this->never()) ->method('setResponse'); @@ -197,4 +215,263 @@ class http_auth_subscriber_test extends \phpbb_test_case $this->subscriber->on_kernel_request($event); } + + public function test_no_credentials() + { + $this->user->data = ['is_registered' => false]; + + $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes = $this->getMockBuilder('\Symfony\Component\HttpFoundation\ParameterBag') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes->expects($this->once()) + ->method('get') + ->with('_route') + ->willReturn('phpbb_feed_overall'); + + $request->expects($this->once()) + ->method('isSecure') + ->willReturn(true); + + $event = $this->getMockBuilder('\Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + + $event->expects($this->once()) + ->method('getRequest') + ->willReturn($request); + + /** @var Response $response */ + $response = null; + $event->expects($this->once()) + ->method('setResponse') + ->with($this->isInstanceOf('\Symfony\Component\HttpFoundation\Response')) + ->will($this->returnCallback(function ($newResponse) use (&$response) { + $response = $newResponse; + })); + + $this->subscriber->on_kernel_request($event); + + $this->assertEquals(Response::HTTP_UNAUTHORIZED, $response->getStatusCode()); + $this->assertEquals('NOT_AUTHORISED', $response->getContent()); + $this->assertTrue($response->headers->has('WWW-Authenticate')); + } + + public function test_valid_credentials() + { + $this->user->data = ['is_registered' => false]; + + $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes = $this->getMockBuilder('\Symfony\Component\HttpFoundation\ParameterBag') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes->expects($this->once()) + ->method('get') + ->with('_route') + ->willReturn('phpbb_feed_overall'); + + $this->request->method('is_set') + ->willReturnMap([ + ['PHP_AUTH_USER', request_interface::SERVER, true], + ['PHP_AUTH_PW', request_interface::SERVER, true], + ]); + + $this->request->method('server') + ->willReturnMap([ + ['PHP_AUTH_USER', '', 'valid_user'], + ['PHP_AUTH_PW', '', 'valid_password'], + ]); + + $request->expects($this->once()) + ->method('isSecure') + ->willReturn(true); + + $event = $this->getMockBuilder('\Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + + $event->expects($this->once()) + ->method('getRequest') + ->willReturn($request); + + /** @var Response $response */ + $response = null; + $event->expects($this->never()) + ->method('setResponse'); + + $this->subscriber->on_kernel_request($event); + + $this->assertNull($response); + } + + public function test_valid_credentials_base64() + { + $this->user->data = ['is_registered' => false]; + + $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes = $this->getMockBuilder('\Symfony\Component\HttpFoundation\ParameterBag') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes->expects($this->once()) + ->method('get') + ->with('_route') + ->willReturn('phpbb_feed_overall'); + + $this->request->method('is_set') + ->willReturnMap([ + ['Authorization', request_interface::SERVER, true], + ]); + + $this->request->method('server') + ->willReturnMap([ + ['Authorization', '', 'Basic dmFsaWRfdXNlcjp2YWxpZF9wYXNzd29yZA=='], + ]); + + $request->expects($this->once()) + ->method('isSecure') + ->willReturn(true); + + $event = $this->getMockBuilder('\Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + + $event->expects($this->once()) + ->method('getRequest') + ->willReturn($request); + + /** @var Response $response */ + $response = null; + $event->expects($this->never()) + ->method('setResponse'); + + $this->subscriber->on_kernel_request($event); + + $this->assertNull($response); + } + + public function test_too_many_attempts() + { + $this->user->data = ['is_registered' => false]; + + $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes = $this->getMockBuilder('\Symfony\Component\HttpFoundation\ParameterBag') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes->expects($this->once()) + ->method('get') + ->with('_route') + ->willReturn('phpbb_feed_overall'); + + $this->request->method('is_set') + ->willReturnMap([ + ['PHP_AUTH_USER', request_interface::SERVER, true], + ['PHP_AUTH_PW', request_interface::SERVER, true], + ]); + + $this->request->method('server') + ->willReturnMap([ + ['PHP_AUTH_USER', '', 'attempts_user'], + ['PHP_AUTH_PW', '', 'valid_password'], + ]); + + $request->expects($this->once()) + ->method('isSecure') + ->willReturn(true); + + $event = $this->getMockBuilder('\Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + + $event->expects($this->once()) + ->method('getRequest') + ->willReturn($request); + + /** @var Response $response */ + $response = null; + $event->expects($this->once()) + ->method('setResponse') + ->with($this->isInstanceOf('\Symfony\Component\HttpFoundation\Response')) + ->will($this->returnCallback(function ($newResponse) use (&$response) { + $response = $newResponse; + })); + + $this->subscriber->on_kernel_request($event); + + $this->assertEquals(Response::HTTP_UNAUTHORIZED, $response->getStatusCode()); + $this->assertEquals('NOT_AUTHORISED', $response->getContent()); + $this->assertFalse($response->headers->has('WWW-Authenticate')); + } + + public function test_wrong_credentials() + { + $this->user->data = ['is_registered' => false]; + + $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes = $this->getMockBuilder('\Symfony\Component\HttpFoundation\ParameterBag') + ->disableOriginalConstructor() + ->getMock(); + + $request->attributes->expects($this->once()) + ->method('get') + ->with('_route') + ->willReturn('phpbb_feed_overall'); + + $this->request->method('is_set') + ->willReturnMap([ + ['PHP_AUTH_USER', request_interface::SERVER, true], + ['PHP_AUTH_PW', request_interface::SERVER, true], + ]); + + $this->request->method('server') + ->willReturnMap([ + ['PHP_AUTH_USER', '', 'invalid_user'], + ['PHP_AUTH_PW', '', 'invalid_password'], + ]); + + $request->expects($this->once()) + ->method('isSecure') + ->willReturn(true); + + $event = $this->getMockBuilder('\Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->disableOriginalConstructor() + ->getMock(); + + $event->expects($this->once()) + ->method('getRequest') + ->willReturn($request); + + /** @var Response $response */ + $response = null; + $event->expects($this->once()) + ->method('setResponse') + ->with($this->isInstanceOf('\Symfony\Component\HttpFoundation\Response')) + ->will($this->returnCallback(function ($newResponse) use (&$response) { + $response = $newResponse; + })); + + $this->subscriber->on_kernel_request($event); + + $this->assertEquals(Response::HTTP_UNAUTHORIZED, $response->getStatusCode()); + $this->assertEquals('NOT_AUTHORISED', $response->getContent()); + $this->assertTrue($response->headers->has('WWW-Authenticate')); + } }