nextcloud/tests/lib/appframework/http/RequestTest.php
Lukas Reschke 202530f4f3
Soften the cookie check if no cookies are sent
When no cookies are sent it is not required to perform any check for the strict or lax cookie, it does not provide any significant security advantage.

It does however interfer with the Android client which requests thumbnails from the unofficial API at `/index.php/apps/files/api/v1/thumbnail/256/256/{filename}`. This endpoint expects the strict cookie to be existent to not leak the existence of files. The Android client authenticates against this endpoint using Basic Auth and without cookies in some cases at least. This will make these endpoints work again with such cases.

To test this issue the following cURL command once without the patch and once with:

> curl http://localhost/index.php/apps/files/api/v1/thumbnail/256/256/welcome.txt  -u admin -v

Without the patch the request is redirected (which the client does not obey) and with the patch the preview is returned.
2016-06-15 11:50:26 +02:00

1706 lines
No EOL
39 KiB
PHP

<?php
/**
* @copyright 2013 Thomas Tanghus (thomas@tanghus.net)
* @copyright 2016 Lukas Reschke lukas@owncloud.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace Test\AppFramework\Http;
use OC\AppFramework\Http\Request;
use OC\Security\CSRF\CsrfToken;
use OC\Security\CSRF\CsrfTokenManager;
use OCP\Security\ISecureRandom;
use OCP\IConfig;
/**
* Class RequestTest
*
* @package OC\AppFramework\Http
*/
class RequestTest extends \Test\TestCase {
/** @var string */
protected $stream = 'fakeinput://data';
/** @var ISecureRandom */
protected $secureRandom;
/** @var IConfig */
protected $config;
/** @var CsrfTokenManager */
protected $csrfTokenManager;
protected function setUp() {
parent::setUp();
require_once __DIR__ . '/requeststream.php';
if (in_array('fakeinput', stream_get_wrappers())) {
stream_wrapper_unregister('fakeinput');
}
stream_wrapper_register('fakeinput', 'RequestStream');
$this->secureRandom = $this->getMockBuilder('\OCP\Security\ISecureRandom')->getMock();
$this->config = $this->getMockBuilder('\OCP\IConfig')->getMock();
$this->csrfTokenManager = $this->getMockBuilder('\OC\Security\CSRF\CsrfTokenManager')
->disableOriginalConstructor()->getMock();
}
protected function tearDown() {
stream_wrapper_unregister('fakeinput');
parent::tearDown();
}
public function testRequestAccessors() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
'method' => 'GET',
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
// Countable
$this->assertSame(2, count($request));
// Array access
$this->assertSame('Joey', $request['nickname']);
// "Magic" accessors
$this->assertSame('Joey', $request->{'nickname'});
$this->assertTrue(isset($request['nickname']));
$this->assertTrue(isset($request->{'nickname'}));
$this->assertFalse(isset($request->{'flickname'}));
// Only testing 'get', but same approach for post, files etc.
$this->assertSame('Joey', $request->get['nickname']);
// Always returns null if variable not set.
$this->assertSame(null, $request->{'flickname'});
}
// urlParams has precedence over POST which has precedence over GET
public function testPrecedence() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
'post' => array('name' => 'Jane Doe', 'nickname' => 'Janey'),
'urlParams' => array('user' => 'jw', 'name' => 'Johnny Weissmüller'),
'method' => 'GET'
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame(3, count($request));
$this->assertSame('Janey', $request->{'nickname'});
$this->assertSame('Johnny Weissmüller', $request->{'name'});
}
/**
* @expectedException \RuntimeException
*/
public function testImmutableArrayAccess() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
'method' => 'GET'
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$request['nickname'] = 'Janey';
}
/**
* @expectedException \RuntimeException
*/
public function testImmutableMagicAccess() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
'method' => 'GET'
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$request->{'nickname'} = 'Janey';
}
/**
* @expectedException \LogicException
*/
public function testGetTheMethodRight() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
'method' => 'GET',
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$request->post;
}
public function testTheMethodIsRight() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
'method' => 'GET',
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('GET', $request->method);
$result = $request->get;
$this->assertSame('John Q. Public', $result['name']);
$this->assertSame('Joey', $result['nickname']);
}
public function testJsonPost() {
global $data;
$data = '{"name": "John Q. Public", "nickname": "Joey"}';
$vars = array(
'method' => 'POST',
'server' => array('CONTENT_TYPE' => 'application/json; utf-8')
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('POST', $request->method);
$result = $request->post;
$this->assertSame('John Q. Public', $result['name']);
$this->assertSame('Joey', $result['nickname']);
$this->assertSame('Joey', $request->params['nickname']);
$this->assertSame('Joey', $request['nickname']);
}
public function testNotJsonPost() {
global $data;
$data = 'this is not valid json';
$vars = array(
'method' => 'POST',
'server' => array('CONTENT_TYPE' => 'application/json; utf-8')
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertEquals('POST', $request->method);
$result = $request->post;
// ensure there's no error attempting to decode the content
}
public function testPatch() {
global $data;
$data = http_build_query(array('name' => 'John Q. Public', 'nickname' => 'Joey'), '', '&');
$vars = array(
'method' => 'PATCH',
'server' => array('CONTENT_TYPE' => 'application/x-www-form-urlencoded'),
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('PATCH', $request->method);
$result = $request->patch;
$this->assertSame('John Q. Public', $result['name']);
$this->assertSame('Joey', $result['nickname']);
}
public function testJsonPatchAndPut() {
global $data;
// PUT content
$data = '{"name": "John Q. Public", "nickname": "Joey"}';
$vars = array(
'method' => 'PUT',
'server' => array('CONTENT_TYPE' => 'application/json; utf-8'),
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('PUT', $request->method);
$result = $request->put;
$this->assertSame('John Q. Public', $result['name']);
$this->assertSame('Joey', $result['nickname']);
// PATCH content
$data = '{"name": "John Q. Public", "nickname": null}';
$vars = array(
'method' => 'PATCH',
'server' => array('CONTENT_TYPE' => 'application/json; utf-8'),
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('PATCH', $request->method);
$result = $request->patch;
$this->assertSame('John Q. Public', $result['name']);
$this->assertSame(null, $result['nickname']);
}
public function testPutStream() {
global $data;
$data = file_get_contents(__DIR__ . '/../../../data/testimage.png');
$vars = array(
'put' => $data,
'method' => 'PUT',
'server' => array('CONTENT_TYPE' => 'image/png'),
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('PUT', $request->method);
$resource = $request->put;
$contents = stream_get_contents($resource);
$this->assertSame($data, $contents);
try {
$resource = $request->put;
} catch(\LogicException $e) {
return;
}
$this->fail('Expected LogicException.');
}
public function testSetUrlParameters() {
$vars = array(
'post' => array(),
'method' => 'POST',
'urlParams' => array('id' => '2'),
);
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$newParams = array('id' => '3', 'test' => 'test2');
$request->setUrlParameters($newParams);
$this->assertSame('test2', $request->getParam('test'));
$this->assertEquals('3', $request->getParam('id'));
$this->assertEquals('3', $request->getParams()['id']);
}
public function testGetIdWithModUnique() {
$vars = [
'server' => [
'UNIQUE_ID' => 'GeneratedUniqueIdByModUnique'
],
];
$request = new Request(
$vars,
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('GeneratedUniqueIdByModUnique', $request->getId());
}
public function testGetIdWithoutModUnique() {
$this->secureRandom->expects($this->once())
->method('generate')
->with('20')
->will($this->returnValue('GeneratedByOwnCloudItself'));
$request = new Request(
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('GeneratedByOwnCloudItself', $request->getId());
}
public function testGetIdWithoutModUniqueStable() {
$request = new Request(
[],
\OC::$server->getSecureRandom(),
$this->config,
$this->csrfTokenManager,
$this->stream
);
$firstId = $request->getId();
$secondId = $request->getId();
$this->assertSame($firstId, $secondId);
}
public function testGetRemoteAddressWithoutTrustedRemote() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('trusted_proxies')
->will($this->returnValue([]));
$request = new Request(
[
'server' => [
'REMOTE_ADDR' => '10.0.0.2',
'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('10.0.0.2', $request->getRemoteAddress());
}
public function testGetRemoteAddressWithNoTrustedHeader() {
$this->config
->expects($this->at(0))
->method('getSystemValue')
->with('trusted_proxies')
->will($this->returnValue(['10.0.0.2']));
$this->config
->expects($this->at(1))
->method('getSystemValue')
->with('forwarded_for_headers')
->will($this->returnValue([]));
$request = new Request(
[
'server' => [
'REMOTE_ADDR' => '10.0.0.2',
'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('10.0.0.2', $request->getRemoteAddress());
}
public function testGetRemoteAddressWithSingleTrustedRemote() {
$this->config
->expects($this->at(0))
->method('getSystemValue')
->with('trusted_proxies')
->will($this->returnValue(['10.0.0.2']));
$this->config
->expects($this->at(1))
->method('getSystemValue')
->with('forwarded_for_headers')
->will($this->returnValue(['HTTP_X_FORWARDED']));
$request = new Request(
[
'server' => [
'REMOTE_ADDR' => '10.0.0.2',
'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('10.4.0.5', $request->getRemoteAddress());
}
public function testGetRemoteAddressVerifyPriorityHeader() {
$this->config
->expects($this->at(0))
->method('getSystemValue')
->with('trusted_proxies')
->will($this->returnValue(['10.0.0.2']));
$this->config
->expects($this->at(1))
->method('getSystemValue')
->with('forwarded_for_headers')
->will($this->returnValue([
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED'
]));
$request = new Request(
[
'server' => [
'REMOTE_ADDR' => '10.0.0.2',
'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4',
'HTTP_X_FORWARDED_FOR' => '192.168.0.233'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('192.168.0.233', $request->getRemoteAddress());
}
/**
* @return array
*/
public function httpProtocolProvider() {
return [
// Valid HTTP 1.0
['HTTP/1.0', 'HTTP/1.0'],
['http/1.0', 'HTTP/1.0'],
['HTTp/1.0', 'HTTP/1.0'],
// Valid HTTP 1.1
['HTTP/1.1', 'HTTP/1.1'],
['http/1.1', 'HTTP/1.1'],
['HTTp/1.1', 'HTTP/1.1'],
// Valid HTTP 2.0
['HTTP/2', 'HTTP/2'],
['http/2', 'HTTP/2'],
['HTTp/2', 'HTTP/2'],
// Invalid
['HTTp/394', 'HTTP/1.1'],
['InvalidProvider/1.1', 'HTTP/1.1'],
[null, 'HTTP/1.1'],
['', 'HTTP/1.1'],
];
}
/**
* @dataProvider httpProtocolProvider
*
* @param mixed $input
* @param string $expected
*/
public function testGetHttpProtocol($input, $expected) {
$request = new Request(
[
'server' => [
'SERVER_PROTOCOL' => $input,
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame($expected, $request->getHttpProtocol());
}
public function testGetServerProtocolWithOverride() {
$this->config
->expects($this->at(0))
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue('customProtocol'));
$this->config
->expects($this->at(1))
->method('getSystemValue')
->with('overwritecondaddr')
->will($this->returnValue(''));
$this->config
->expects($this->at(2))
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue('customProtocol'));
$request = new Request(
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('customProtocol', $request->getServerProtocol());
}
public function testGetServerProtocolWithProtoValid() {
$this->config
->expects($this->exactly(2))
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue(''));
$requestHttps = new Request(
[
'server' => [
'HTTP_X_FORWARDED_PROTO' => 'HtTpS'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$requestHttp = new Request(
[
'server' => [
'HTTP_X_FORWARDED_PROTO' => 'HTTp'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('https', $requestHttps->getServerProtocol());
$this->assertSame('http', $requestHttp->getServerProtocol());
}
public function testGetServerProtocolWithHttpsServerValueOn() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue(''));
$request = new Request(
[
'server' => [
'HTTPS' => 'on'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('https', $request->getServerProtocol());
}
public function testGetServerProtocolWithHttpsServerValueOff() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue(''));
$request = new Request(
[
'server' => [
'HTTPS' => 'off'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('http', $request->getServerProtocol());
}
public function testGetServerProtocolWithHttpsServerValueEmpty() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue(''));
$request = new Request(
[
'server' => [
'HTTPS' => ''
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('http', $request->getServerProtocol());
}
public function testGetServerProtocolDefault() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue(''));
$request = new Request(
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('http', $request->getServerProtocol());
}
public function testGetServerProtocolBehindLoadBalancers() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('overwriteprotocol')
->will($this->returnValue(''));
$request = new Request(
[
'server' => [
'HTTP_X_FORWARDED_PROTO' => 'https,http,http'
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('https', $request->getServerProtocol());
}
/**
* @dataProvider userAgentProvider
* @param string $testAgent
* @param array $userAgent
* @param bool $matches
*/
public function testUserAgent($testAgent, $userAgent, $matches) {
$request = new Request(
[
'server' => [
'HTTP_USER_AGENT' => $testAgent,
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame($matches, $request->isUserAgent($userAgent));
}
/**
* @dataProvider userAgentProvider
* @param string $testAgent
* @param array $userAgent
* @param bool $matches
*/
public function testUndefinedUserAgent($testAgent, $userAgent, $matches) {
$request = new Request(
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertFalse($request->isUserAgent($userAgent));
}
/**
* @return array
*/
function userAgentProvider() {
return [
[
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
[
Request::USER_AGENT_IE
],
true,
],
[
'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0',
[
Request::USER_AGENT_IE
],
false,
],
[
'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36',
[
Request::USER_AGENT_ANDROID_MOBILE_CHROME
],
true,
],
[
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
[
Request::USER_AGENT_ANDROID_MOBILE_CHROME
],
false,
],
[
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
[
Request::USER_AGENT_IE,
Request::USER_AGENT_ANDROID_MOBILE_CHROME,
],
true,
],
[
'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36',
[
Request::USER_AGENT_IE,
Request::USER_AGENT_ANDROID_MOBILE_CHROME,
],
true,
],
[
'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0',
[
Request::USER_AGENT_FREEBOX
],
false,
],
[
'Mozilla/5.0',
[
Request::USER_AGENT_FREEBOX
],
true,
],
[
'Fake Mozilla/5.0',
[
Request::USER_AGENT_FREEBOX
],
false,
],
];
}
public function testInsecureServerHostServerNameHeader() {
$request = new Request(
[
'server' => [
'SERVER_NAME' => 'from.server.name:8080',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('from.server.name:8080', $request->getInsecureServerHost());
}
public function testInsecureServerHostHttpHostHeader() {
$request = new Request(
[
'server' => [
'SERVER_NAME' => 'from.server.name:8080',
'HTTP_HOST' => 'from.host.header:8080',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('from.host.header:8080', $request->getInsecureServerHost());
}
public function testInsecureServerHostHttpFromForwardedHeaderSingle() {
$request = new Request(
[
'server' => [
'SERVER_NAME' => 'from.server.name:8080',
'HTTP_HOST' => 'from.host.header:8080',
'HTTP_X_FORWARDED_HOST' => 'from.forwarded.host:8080',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('from.forwarded.host:8080', $request->getInsecureServerHost());
}
public function testInsecureServerHostHttpFromForwardedHeaderStacked() {
$request = new Request(
[
'server' => [
'SERVER_NAME' => 'from.server.name:8080',
'HTTP_HOST' => 'from.host.header:8080',
'HTTP_X_FORWARDED_HOST' => 'from.forwarded.host2:8080,another.one:9000',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('from.forwarded.host2:8080', $request->getInsecureServerHost());
}
public function testGetServerHostWithOverwriteHost() {
$this->config
->expects($this->at(0))
->method('getSystemValue')
->with('overwritehost')
->will($this->returnValue('my.overwritten.host'));
$this->config
->expects($this->at(1))
->method('getSystemValue')
->with('overwritecondaddr')
->will($this->returnValue(''));
$this->config
->expects($this->at(2))
->method('getSystemValue')
->with('overwritehost')
->will($this->returnValue('my.overwritten.host'));
$request = new Request(
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('my.overwritten.host', $request->getServerHost());
}
public function testGetServerHostWithTrustedDomain() {
$this->config
->expects($this->at(3))
->method('getSystemValue')
->with('trusted_domains')
->will($this->returnValue(['my.trusted.host']));
$request = new Request(
[
'server' => [
'HTTP_X_FORWARDED_HOST' => 'my.trusted.host',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('my.trusted.host', $request->getServerHost());
}
public function testGetServerHostWithUntrustedDomain() {
$this->config
->expects($this->at(3))
->method('getSystemValue')
->with('trusted_domains')
->will($this->returnValue(['my.trusted.host']));
$this->config
->expects($this->at(4))
->method('getSystemValue')
->with('trusted_domains')
->will($this->returnValue(['my.trusted.host']));
$request = new Request(
[
'server' => [
'HTTP_X_FORWARDED_HOST' => 'my.untrusted.host',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('my.trusted.host', $request->getServerHost());
}
public function testGetServerHostWithNoTrustedDomain() {
$this->config
->expects($this->at(3))
->method('getSystemValue')
->with('trusted_domains')
->will($this->returnValue([]));
$this->config
->expects($this->at(4))
->method('getSystemValue')
->with('trusted_domains')
->will($this->returnValue([]));
$request = new Request(
[
'server' => [
'HTTP_X_FORWARDED_HOST' => 'my.untrusted.host',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('', $request->getServerHost());
}
public function testGetOverwriteHostDefaultNull() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('overwritehost')
->will($this->returnValue(''));
$request = new Request(
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertNull(self::invokePrivate($request, 'getOverwriteHost'));
}
public function testGetOverwriteHostWithOverwrite() {
$this->config
->expects($this->at(0))
->method('getSystemValue')
->with('overwritehost')
->will($this->returnValue('www.owncloud.org'));
$this->config
->expects($this->at(1))
->method('getSystemValue')
->with('overwritecondaddr')
->will($this->returnValue(''));
$this->config
->expects($this->at(2))
->method('getSystemValue')
->with('overwritehost')
->will($this->returnValue('www.owncloud.org'));
$request = new Request(
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('www.owncloud.org', self::invokePrivate($request, 'getOverwriteHost'));
}
public function testGetPathInfoWithSetEnv() {
$request = new Request(
[
'server' => [
'PATH_INFO' => 'apps/files/',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('apps/files/', $request->getPathInfo());
}
/**
* @expectedException \Exception
* @expectedExceptionMessage The requested uri(/foo.php) cannot be processed by the script '/var/www/index.php')
*/
public function testGetPathInfoNotProcessible() {
$request = new Request(
[
'server' => [
'REQUEST_URI' => '/foo.php',
'SCRIPT_NAME' => '/var/www/index.php',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$request->getPathInfo();
}
/**
* @expectedException \Exception
* @expectedExceptionMessage The requested uri(/foo.php) cannot be processed by the script '/var/www/index.php')
*/
public function testGetRawPathInfoNotProcessible() {
$request = new Request(
[
'server' => [
'REQUEST_URI' => '/foo.php',
'SCRIPT_NAME' => '/var/www/index.php',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$request->getRawPathInfo();
}
/**
* @dataProvider genericPathInfoProvider
* @param string $requestUri
* @param string $scriptName
* @param string $expected
*/
public function testGetPathInfoWithoutSetEnvGeneric($requestUri, $scriptName, $expected) {
$request = new Request(
[
'server' => [
'REQUEST_URI' => $requestUri,
'SCRIPT_NAME' => $scriptName,
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame($expected, $request->getPathInfo());
}
/**
* @dataProvider genericPathInfoProvider
* @param string $requestUri
* @param string $scriptName
* @param string $expected
*/
public function testGetRawPathInfoWithoutSetEnvGeneric($requestUri, $scriptName, $expected) {
$request = new Request(
[
'server' => [
'REQUEST_URI' => $requestUri,
'SCRIPT_NAME' => $scriptName,
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame($expected, $request->getRawPathInfo());
}
/**
* @dataProvider rawPathInfoProvider
* @param string $requestUri
* @param string $scriptName
* @param string $expected
*/
public function testGetRawPathInfoWithoutSetEnv($requestUri, $scriptName, $expected) {
$request = new Request(
[
'server' => [
'REQUEST_URI' => $requestUri,
'SCRIPT_NAME' => $scriptName,
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame($expected, $request->getRawPathInfo());
}
/**
* @dataProvider pathInfoProvider
* @param string $requestUri
* @param string $scriptName
* @param string $expected
*/
public function testGetPathInfoWithoutSetEnv($requestUri, $scriptName, $expected) {
$request = new Request(
[
'server' => [
'REQUEST_URI' => $requestUri,
'SCRIPT_NAME' => $scriptName,
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame($expected, $request->getPathInfo());
}
/**
* @return array
*/
public function genericPathInfoProvider() {
return [
['/core/index.php?XDEBUG_SESSION_START=14600', '/core/index.php', ''],
['/index.php/apps/files/', 'index.php', '/apps/files/'],
['/index.php/apps/files/../&amp;/&?someQueryParameter=QueryParam', 'index.php', '/apps/files/../&amp;/&'],
['/remote.php/漢字編碼方法 / 汉字编码方法', 'remote.php', '/漢字編碼方法 / 汉字编码方法'],
['///removeTrailin//gSlashes///', 'remote.php', '/removeTrailin/gSlashes/'],
['/', '/', ''],
['', '', ''],
];
}
/**
* @return array
*/
public function rawPathInfoProvider() {
return [
['/foo%2Fbar/subfolder', '', 'foo%2Fbar/subfolder'],
];
}
/**
* @return array
*/
public function pathInfoProvider() {
return [
['/foo%2Fbar/subfolder', '', 'foo/bar/subfolder'],
];
}
public function testGetRequestUriWithoutOverwrite() {
$this->config
->expects($this->once())
->method('getSystemValue')
->with('overwritewebroot')
->will($this->returnValue(''));
$request = new Request(
[
'server' => [
'REQUEST_URI' => '/test.php'
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
);
$this->assertSame('/test.php', $request->getRequestUri());
}
public function providesGetRequestUriWithOverwriteData() {
return [
['/scriptname.php/some/PathInfo', '/owncloud/', ''],
['/scriptname.php/some/PathInfo', '/owncloud/', '123'],
];
}
/**
* @dataProvider providesGetRequestUriWithOverwriteData
*/
public function testGetRequestUriWithOverwrite($expectedUri, $overwriteWebRoot, $overwriteCondAddr) {
$this->config
->expects($this->at(0))
->method('getSystemValue')
->with('overwritewebroot')
->will($this->returnValue($overwriteWebRoot));
$this->config
->expects($this->at(1))
->method('getSystemValue')
->with('overwritecondaddr')
->will($this->returnValue($overwriteCondAddr));
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'REQUEST_URI' => '/test.php/some/PathInfo',
'SCRIPT_NAME' => '/test.php',
]
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$request
->expects($this->once())
->method('getScriptName')
->will($this->returnValue('/scriptname.php'));
$this->assertSame($expectedUri, $request->getRequestUri());
}
public function testPassesCSRFCheckWithGet() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'get' => [
'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookiestrict' => 'true',
'nc_sameSiteCookielax' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$token = new CsrfToken('AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds');
$this->csrfTokenManager
->expects($this->once())
->method('isTokenValid')
->with($token)
->willReturn(true);
$this->assertTrue($request->passesCSRFCheck());
}
public function testPassesCSRFCheckWithPost() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookiestrict' => 'true',
'nc_sameSiteCookielax' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$token = new CsrfToken('AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds');
$this->csrfTokenManager
->expects($this->once())
->method('isTokenValid')
->with($token)
->willReturn(true);
$this->assertTrue($request->passesCSRFCheck());
}
public function testPassesCSRFCheckWithHeader() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookiestrict' => 'true',
'nc_sameSiteCookielax' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$token = new CsrfToken('AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds');
$this->csrfTokenManager
->expects($this->once())
->method('isTokenValid')
->with($token)
->willReturn(true);
$this->assertTrue($request->passesCSRFCheck());
}
public function testPassesCSRFCheckWithGetAndWithoutCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'get' => [
'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->csrfTokenManager
->expects($this->once())
->method('isTokenValid')
->willReturn(true);
$this->assertTrue($request->passesCSRFCheck());
}
public function testPassesCSRFCheckWithPostAndWithoutCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->csrfTokenManager
->expects($this->once())
->method('isTokenValid')
->willReturn(true);
$this->assertTrue($request->passesCSRFCheck());
}
public function testPassesCSRFCheckWithHeaderAndWithoutCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->csrfTokenManager
->expects($this->once())
->method('isTokenValid')
->willReturn(true);
$this->assertTrue($request->passesCSRFCheck());
}
public function testFailsCSRFCheckWithHeaderAndNotAllChecksPassing() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookiestrict' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->csrfTokenManager
->expects($this->never())
->method('isTokenValid');
$this->assertFalse($request->passesCSRFCheck());
}
public function testPassesStrictCookieCheckWithAllCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookiestrict' => 'true',
'nc_sameSiteCookielax' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->assertTrue($request->passesStrictCookieCheck());
}
public function testFailsSRFCheckWithPostAndWithCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'foo' => 'bar',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->csrfTokenManager
->expects($this->never())
->method('isTokenValid');
$this->assertFalse($request->passesCSRFCheck());
}
public function testFailStrictCookieCheckWithOnlyLaxCookie() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookielax' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->assertFalse($request->passesStrictCookieCheck());
}
public function testFailStrictCookieCheckWithOnlyStrictCookie() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookiestrict' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->assertFalse($request->passesStrictCookieCheck());
}
public function testPassesLaxCookieCheck() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookielax' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->assertTrue($request->passesLaxCookieCheck());
}
public function testFailsLaxCookieCheckWithOnlyStrictCookie() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'nc_sameSiteCookiestrict' => 'true',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->assertFalse($request->passesLaxCookieCheck());
}
/**
* @return array
*/
public function invalidTokenDataProvider() {
return [
['InvalidSentToken'],
['InvalidSentToken:InvalidSecret'],
[null],
[''],
];
}
/**
* @dataProvider invalidTokenDataProvider
* @param string $invalidToken
*/
public function testPassesCSRFCheckWithInvalidToken($invalidToken) {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => $invalidToken,
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$token = new CsrfToken($invalidToken);
$this->csrfTokenManager
->expects($this->any())
->method('isTokenValid')
->with($token)
->willReturn(false);
$this->assertFalse($request->passesCSRFCheck());
}
public function testPassesCSRFCheckWithoutTokenFail() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->assertFalse($request->passesCSRFCheck());
}
}