diff options
Diffstat (limited to 'tests/lib/Http/Client/ClientTest.php')
-rw-r--r-- | tests/lib/Http/Client/ClientTest.php | 339 |
1 files changed, 168 insertions, 171 deletions
diff --git a/tests/lib/Http/Client/ClientTest.php b/tests/lib/Http/Client/ClientTest.php index 63835a4d4cd..e76b66b52d7 100644 --- a/tests/lib/Http/Client/ClientTest.php +++ b/tests/lib/Http/Client/ClientTest.php @@ -1,21 +1,25 @@ <?php + +declare(strict_types=1); + /** - * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Http\Client; use GuzzleHttp\Psr7\Response; use OC\Http\Client\Client; -use OC\Http\Client\LocalAddressChecker; use OC\Security\CertificateManager; use OCP\Http\Client\LocalServerException; use OCP\ICertificateManager; use OCP\IConfig; +use OCP\Security\IRemoteHostValidator; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use function parse_url; /** * Class ClientTest @@ -29,8 +33,9 @@ class ClientTest extends \Test\TestCase { private $client; /** @var IConfig|MockObject */ private $config; - /** @var LocalAddressChecker|MockObject */ - private $localAddressChecker; + /** @var IRemoteHostValidator|MockObject */ + private IRemoteHostValidator $remoteHostValidator; + private LoggerInterface $logger; /** @var array */ private $defaultRequestOptions; @@ -39,33 +44,38 @@ class ClientTest extends \Test\TestCase { $this->config = $this->createMock(IConfig::class); $this->guzzleClient = $this->createMock(\GuzzleHttp\Client::class); $this->certificateManager = $this->createMock(ICertificateManager::class); - $this->localAddressChecker = $this->createMock(LocalAddressChecker::class); + $this->remoteHostValidator = $this->createMock(IRemoteHostValidator::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->client = new Client( $this->config, $this->certificateManager, $this->guzzleClient, - $this->localAddressChecker + $this->remoteHostValidator, + $this->logger, ); } public function testGetProxyUri(): void { $this->config - ->method('getSystemValue') - ->with('proxy', null) - ->willReturn(null); + ->method('getSystemValueString') + ->with('proxy', '') + ->willReturn(''); $this->assertNull(self::invokePrivate($this->client, 'getProxyUri')); } public function testGetProxyUriProxyHostEmptyPassword(): void { - $map = [ - ['proxy', '', 'foo'], - ['proxyuserpwd', '', null], - ['proxyexclude', [], []], - ]; - $this->config ->method('getSystemValue') - ->will($this->returnValueMap($map)); + ->willReturnMap([ + ['proxyexclude', [], []], + ]); + + $this->config + ->method('getSystemValueString') + ->willReturnMap([ + ['proxy', '', 'foo'], + ['proxyuserpwd', '', ''], + ]); $this->assertEquals([ 'http' => 'foo', @@ -75,35 +85,17 @@ class ClientTest extends \Test\TestCase { public function testGetProxyUriProxyHostWithPassword(): void { $this->config - ->expects($this->at(0)) - ->method('getSystemValue') - ->with( - $this->equalTo('proxy'), - $this->callback(function ($input) { - return $input === ''; - }) - ) - ->willReturn('foo'); - $this->config - ->expects($this->at(1)) - ->method('getSystemValue') - ->with( - $this->equalTo('proxyuserpwd'), - $this->callback(function ($input) { - return $input === ''; - }) - ) - ->willReturn('username:password'); - $this->config - ->expects($this->at(2)) + ->expects($this->once()) ->method('getSystemValue') - ->with( - $this->equalTo('proxyexclude'), - $this->callback(function ($input) { - return $input === []; - }) - ) + ->with('proxyexclude', []) ->willReturn([]); + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValueString') + ->willReturnMap([ + ['proxy', '', 'foo'], + ['proxyuserpwd', '', 'username:password'], + ]); $this->assertEquals([ 'http' => 'username:password@foo', 'https' => 'username:password@foo' @@ -112,35 +104,17 @@ class ClientTest extends \Test\TestCase { public function testGetProxyUriProxyHostWithPasswordAndExclude(): void { $this->config - ->expects($this->at(0)) - ->method('getSystemValue') - ->with( - $this->equalTo('proxy'), - $this->callback(function ($input) { - return $input === ''; - }) - ) - ->willReturn('foo'); - $this->config - ->expects($this->at(1)) - ->method('getSystemValue') - ->with( - $this->equalTo('proxyuserpwd'), - $this->callback(function ($input) { - return $input === ''; - }) - ) - ->willReturn('username:password'); - $this->config - ->expects($this->at(2)) + ->expects($this->once()) ->method('getSystemValue') - ->with( - $this->equalTo('proxyexclude'), - $this->callback(function ($input) { - return $input === []; - }) - ) + ->with('proxyexclude', []) ->willReturn(['bar']); + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValueString') + ->willReturnMap([ + ['proxy', '', 'foo'], + ['proxyuserpwd', '', 'username:password'], + ]); $this->assertEquals([ 'http' => 'username:password@foo', 'https' => 'username:password@foo', @@ -148,145 +122,153 @@ class ClientTest extends \Test\TestCase { ], self::invokePrivate($this->client, 'getProxyUri')); } - public function dataPreventLocalAddress():array { + public function testPreventLocalAddressThrowOnInvalidUri(): void { + $this->expectException(LocalServerException::class); + $this->expectExceptionMessage('Could not detect any host'); + + self::invokePrivate($this->client, 'preventLocalAddress', ['!@#$', []]); + } + + public static function dataPreventLocalAddress(): array { return [ - ['localhost/foo.bar'], - ['localHost/foo.bar'], - ['random-host/foo.bar'], - ['[::1]/bla.blub'], - ['[::]/bla.blub'], - ['192.168.0.1'], - ['172.16.42.1'], - ['[fdf8:f53b:82e4::53]/secret.ics'], - ['[fe80::200:5aee:feaa:20a2]/secret.ics'], - ['[0:0:0:0:0:0:10.0.0.1]/secret.ics'], - ['[0:0:0:0:0:ffff:127.0.0.0]/secret.ics'], - ['10.0.0.1'], - ['another-host.local'], - ['service.localhost'], - ['!@#$'], // test invalid url + ['https://localhost/foo.bar'], + ['https://localHost/foo.bar'], + ['https://random-host/foo.bar'], + ['https://[::1]/bla.blub'], + ['https://[::]/bla.blub'], + ['https://192.168.0.1'], + ['https://172.16.42.1'], + ['https://[fdf8:f53b:82e4::53]/secret.ics'], + ['https://[fe80::200:5aee:feaa:20a2]/secret.ics'], + ['https://[0:0:0:0:0:0:10.0.0.1]/secret.ics'], + ['https://[0:0:0:0:0:ffff:127.0.0.0]/secret.ics'], + ['https://10.0.0.1'], + ['https://another-host.local'], + ['https://service.localhost'], + ['https://normal.host.com'], + ['https://com.one-.nextcloud-one.com'], ]; } /** - * @dataProvider dataPreventLocalAddress * @param string $uri */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataPreventLocalAddress')] public function testPreventLocalAddressDisabledByGlobalConfig(string $uri): void { $this->config->expects($this->once()) ->method('getSystemValueBool') ->with('allow_local_remote_servers', false) ->willReturn(true); -// $this->expectException(LocalServerException::class); - - self::invokePrivate($this->client, 'preventLocalAddress', ['http://' . $uri, []]); + self::invokePrivate($this->client, 'preventLocalAddress', [$uri, []]); } /** - * @dataProvider dataPreventLocalAddress * @param string $uri */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataPreventLocalAddress')] public function testPreventLocalAddressDisabledByOption(string $uri): void { $this->config->expects($this->never()) ->method('getSystemValueBool'); -// $this->expectException(LocalServerException::class); - - self::invokePrivate($this->client, 'preventLocalAddress', ['http://' . $uri, [ + self::invokePrivate($this->client, 'preventLocalAddress', [$uri, [ 'nextcloud' => ['allow_local_address' => true], ]]); } /** - * @dataProvider dataPreventLocalAddress * @param string $uri */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataPreventLocalAddress')] public function testPreventLocalAddressOnGet(string $uri): void { + $host = parse_url($uri, PHP_URL_HOST); $this->expectException(LocalServerException::class); - $this->localAddressChecker - ->expects($this->once()) - ->method('ThrowIfLocalAddress') - ->with('http://' . $uri) - ->will($this->throwException(new LocalServerException())); + $this->remoteHostValidator + ->method('isValid') + ->with($host) + ->willReturn(false); - $this->client->get('http://' . $uri); + $this->client->get($uri); } /** - * @dataProvider dataPreventLocalAddress * @param string $uri */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataPreventLocalAddress')] public function testPreventLocalAddressOnHead(string $uri): void { + $host = parse_url($uri, PHP_URL_HOST); $this->expectException(LocalServerException::class); - $this->localAddressChecker - ->expects($this->once()) - ->method('ThrowIfLocalAddress') - ->with('http://' . $uri) - ->will($this->throwException(new LocalServerException())); + $this->remoteHostValidator + ->method('isValid') + ->with($host) + ->willReturn(false); - $this->client->head('http://' . $uri); + $this->client->head($uri); } /** - * @dataProvider dataPreventLocalAddress * @param string $uri */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataPreventLocalAddress')] public function testPreventLocalAddressOnPost(string $uri): void { + $host = parse_url($uri, PHP_URL_HOST); $this->expectException(LocalServerException::class); - $this->localAddressChecker - ->expects($this->once()) - ->method('ThrowIfLocalAddress') - ->with('http://' . $uri) - ->will($this->throwException(new LocalServerException())); + $this->remoteHostValidator + ->method('isValid') + ->with($host) + ->willReturn(false); - $this->client->post('http://' . $uri); + $this->client->post($uri); } /** - * @dataProvider dataPreventLocalAddress * @param string $uri */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataPreventLocalAddress')] public function testPreventLocalAddressOnPut(string $uri): void { + $host = parse_url($uri, PHP_URL_HOST); $this->expectException(LocalServerException::class); - $this->localAddressChecker - ->expects($this->once()) - ->method('ThrowIfLocalAddress') - ->with('http://' . $uri) - ->will($this->throwException(new LocalServerException())); + $this->remoteHostValidator + ->method('isValid') + ->with($host) + ->willReturn(false); - $this->client->put('http://' . $uri); + $this->client->put($uri); } /** - * @dataProvider dataPreventLocalAddress * @param string $uri */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataPreventLocalAddress')] public function testPreventLocalAddressOnDelete(string $uri): void { + $host = parse_url($uri, PHP_URL_HOST); $this->expectException(LocalServerException::class); - $this->localAddressChecker - ->expects($this->once()) - ->method('ThrowIfLocalAddress') - ->with('http://' . $uri) - ->will($this->throwException(new LocalServerException())); + $this->remoteHostValidator + ->method('isValid') + ->with($host) + ->willReturn(false); - $this->client->delete('http://' . $uri); + $this->client->delete($uri); } private function setUpDefaultRequestOptions(): void { - $map = [ - ['proxy', '', 'foo'], - ['proxyuserpwd', '', null], - ['proxyexclude', [], []], - ]; - $this->config ->method('getSystemValue') - ->will($this->returnValueMap($map)); + ->willReturnMap([ + ['proxyexclude', [], []], + ]); + $this->config + ->method('getSystemValueString') + ->willReturnMap([ + ['proxy', '', 'foo'], + ['proxyuserpwd', '', ''], + ]); $this->config ->method('getSystemValueBool') - ->with('allow_local_remote_servers', false) - ->willReturn(true); + ->willReturnMap([ + ['installed', false, true], + ['allow_local_remote_servers', false, true], + ]); $this->certificateManager ->expects($this->once()) @@ -469,10 +451,17 @@ class ClientTest extends \Test\TestCase { public function testSetDefaultOptionsWithNotInstalled(): void { $this->config - ->expects($this->at(1)) - ->method('getSystemValue') - ->with('installed', false) - ->willReturn(false); + ->expects($this->exactly(2)) + ->method('getSystemValueBool') + ->willReturnMap([ + ['installed', false, false], + ['allow_local_remote_servers', false, false], + ]); + $this->config + ->expects($this->once()) + ->method('getSystemValueString') + ->with('proxy', '') + ->willReturn(''); $this->certificateManager ->expects($this->never()) ->method('listCertificates'); @@ -491,8 +480,8 @@ class ClientTest extends \Test\TestCase { 'on_redirect' => function ( \Psr\Http\Message\RequestInterface $request, \Psr\Http\Message\ResponseInterface $response, - \Psr\Http\Message\UriInterface $uri - ) { + \Psr\Http\Message\UriInterface $uri, + ): void { }, ], ], self::invokePrivate($this->client, 'buildRequestOptions', [[]])); @@ -500,20 +489,24 @@ class ClientTest extends \Test\TestCase { public function testSetDefaultOptionsWithProxy(): void { $this->config - ->expects($this->at(0)) - ->method('getSystemValue') - ->with('proxy', null) - ->willReturn('foo'); - $this->config - ->expects($this->at(1)) - ->method('getSystemValue') - ->with('proxyuserpwd', null) - ->willReturn(null); + ->expects($this->exactly(2)) + ->method('getSystemValueBool') + ->willReturnMap([ + ['installed', false, true], + ['allow_local_remote_servers', false, false], + ]); $this->config - ->expects($this->at(2)) + ->expects($this->once()) ->method('getSystemValue') ->with('proxyexclude', []) ->willReturn([]); + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValueString') + ->willReturnMap([ + ['proxy', '', 'foo'], + ['proxyuserpwd', '', ''], + ]); $this->certificateManager ->expects($this->once()) ->method('getAbsoluteBundlePath') @@ -538,8 +531,8 @@ class ClientTest extends \Test\TestCase { 'on_redirect' => function ( \Psr\Http\Message\RequestInterface $request, \Psr\Http\Message\ResponseInterface $response, - \Psr\Http\Message\UriInterface $uri - ) { + \Psr\Http\Message\UriInterface $uri, + ): void { }, ], ], self::invokePrivate($this->client, 'buildRequestOptions', [[]])); @@ -547,20 +540,24 @@ class ClientTest extends \Test\TestCase { public function testSetDefaultOptionsWithProxyAndExclude(): void { $this->config - ->expects($this->at(0)) - ->method('getSystemValue') - ->with('proxy', null) - ->willReturn('foo'); - $this->config - ->expects($this->at(1)) - ->method('getSystemValue') - ->with('proxyuserpwd', null) - ->willReturn(null); + ->expects($this->exactly(2)) + ->method('getSystemValueBool') + ->willReturnMap([ + ['installed', false, true], + ['allow_local_remote_servers', false, false], + ]); $this->config - ->expects($this->at(2)) + ->expects($this->once()) ->method('getSystemValue') ->with('proxyexclude', []) ->willReturn(['bar']); + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValueString') + ->willReturnMap([ + ['proxy', '', 'foo'], + ['proxyuserpwd', '', ''], + ]); $this->certificateManager ->expects($this->once()) ->method('getAbsoluteBundlePath') @@ -586,8 +583,8 @@ class ClientTest extends \Test\TestCase { 'on_redirect' => function ( \Psr\Http\Message\RequestInterface $request, \Psr\Http\Message\ResponseInterface $response, - \Psr\Http\Message\UriInterface $uri - ) { + \Psr\Http\Message\UriInterface $uri, + ): void { }, ], ], self::invokePrivate($this->client, 'buildRequestOptions', [[]])); |