diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2016-02-25 21:42:20 +0100 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2016-02-25 21:42:20 +0100 |
commit | 290f159a97acd22dac0aac137654b93661a8dc38 (patch) | |
tree | 3578e86cb8a66783c91b625e3af3b6916d5963c9 | |
parent | 84ffc4fbc4c622c751a39e8237dc281a9f0f41e6 (diff) | |
parent | 8b8dcca6c55cb8d7151826fcf86a8b6a25ca4dfb (diff) | |
download | nextcloud-server-290f159a97acd22dac0aac137654b93661a8dc38.tar.gz nextcloud-server-290f159a97acd22dac0aac137654b93661a8dc38.zip |
Merge pull request #22653 from owncloud/integration-tests-for-dav-csrf
Add integration test for CSRF protection on DAV
-rw-r--r-- | build/integration/features/bootstrap/BasicStructure.php | 92 | ||||
-rw-r--r-- | build/integration/features/webdav-related.feature | 37 |
2 files changed, 127 insertions, 2 deletions
diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php index bf3b1d50814..0084597836f 100644 --- a/build/integration/features/bootstrap/BasicStructure.php +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -7,7 +7,7 @@ use GuzzleHttp\Message\ResponseInterface; require __DIR__ . '/../../vendor/autoload.php'; -trait BasicStructure{ +trait BasicStructure { /** @var string */ private $currentUser = ''; @@ -20,6 +20,12 @@ trait BasicStructure{ /** @var ResponseInterface */ private $response = null; + /** @var \GuzzleHttp\Cookie\CookieJar */ + private $cookieJar; + + /** @var string */ + private $requesttoken; + public function __construct($baseUrl, $admin, $regular_user_password) { // Initialize your context here @@ -29,6 +35,7 @@ trait BasicStructure{ $this->localBaseUrl = substr($this->baseUrl, 0, -4); $this->remoteBaseUrl = substr($this->baseUrl, 0, -4); $this->currentServer = 'LOCAL'; + $this->cookieJar = new \GuzzleHttp\Cookie\CookieJar(); // in case of ci deployment we take the server url from the environment $testServerUrl = getenv('TEST_SERVER_URL'); @@ -93,7 +100,6 @@ trait BasicStructure{ /** * @When /^sending "([^"]*)" to "([^"]*)" with$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData */ public function sendingToWith($verb, $url, $body) { $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php" . $url; @@ -136,6 +142,88 @@ trait BasicStructure{ PHPUnit_Framework_Assert::assertEquals($statusCode, $this->response->getStatusCode()); } + /** + * @param ResponseInterface $response + */ + private function extracRequestTokenFromResponse(ResponseInterface $response) { + $this->requesttoken = substr(preg_replace('/(.*)data-requesttoken="(.*)">(.*)/sm', '\2', $response->getBody()->getContents()), 0, 89); + } + + /** + * @Given Logging in using web as :user + */ + public function loggingInUsingWebAs($user) { + $loginUrl = substr($this->baseUrl, 0, -5); + // Request a new session and extract CSRF token + $client = new Client(); + $response = $client->get( + $loginUrl, + [ + 'cookies' => $this->cookieJar, + ] + ); + $this->extracRequestTokenFromResponse($response); + + // Login and extract new token + $password = ($user === 'admin') ? 'admin' : '123456'; + $client = new Client(); + $response = $client->post( + $loginUrl, + [ + 'body' => [ + 'user' => $user, + 'password' => $password, + 'requesttoken' => $this->requesttoken, + ], + 'cookies' => $this->cookieJar, + ] + ); + $this->extracRequestTokenFromResponse($response); + } + + /** + * @When Sending a :method to :url with requesttoken + */ + public function sendingAToWithRequesttoken($method, $url) { + $baseUrl = substr($this->baseUrl, 0, -5); + + $client = new Client(); + $request = $client->createRequest( + $method, + $baseUrl . $url, + [ + 'cookies' => $this->cookieJar, + ] + ); + $request->addHeader('requesttoken', $this->requesttoken); + try { + $this->response = $client->send($request); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When Sending a :method to :url without requesttoken + */ + public function sendingAToWithoutRequesttoken($method, $url) { + $baseUrl = substr($this->baseUrl, 0, -5); + + $client = new Client(); + $request = $client->createRequest( + $method, + $baseUrl . $url, + [ + 'cookies' => $this->cookieJar, + ] + ); + try { + $this->response = $client->send($request); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + public static function removeFile($path, $filename){ if (file_exists("$path" . "$filename")) { unlink("$path" . "$filename"); diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature index c424f77afd5..c4623a01ba2 100644 --- a/build/integration/features/webdav-related.feature +++ b/build/integration/features/webdav-related.feature @@ -62,9 +62,46 @@ Feature: sharing |X-XSS-Protection|1; mode=block| And Downloaded content should start with "Welcome to your ownCloud account!" + Scenario: Doing a GET with a web login should work without CSRF token on the new backend + Given Logging in using web as "admin" + When Sending a "GET" to "/remote.php/dav/files/admin/welcome.txt" without requesttoken + Then Downloaded content should start with "Welcome to your ownCloud account!" + Then the HTTP status code should be "200" + Scenario: Doing a GET with a web login should work with CSRF token on the new backend + Given Logging in using web as "admin" + When Sending a "GET" to "/remote.php/dav/files/admin/welcome.txt" with requesttoken + Then Downloaded content should start with "Welcome to your ownCloud account!" + Then the HTTP status code should be "200" + Scenario: Doing a PROPFIND with a web login should not work without CSRF token on the new backend + Given Logging in using web as "admin" + When Sending a "PROPFIND" to "/remote.php/dav/files/admin/welcome.txt" without requesttoken + Then the HTTP status code should be "401" + Scenario: Doing a PROPFIND with a web login should work with CSRF token on the new backend + Given Logging in using web as "admin" + When Sending a "PROPFIND" to "/remote.php/dav/files/admin/welcome.txt" with requesttoken + Then the HTTP status code should be "207" + Scenario: Doing a GET with a web login should work without CSRF token on the old backend + Given Logging in using web as "admin" + When Sending a "GET" to "/remote.php/webdav/welcome.txt" without requesttoken + Then Downloaded content should start with "Welcome to your ownCloud account!" + Then the HTTP status code should be "200" + Scenario: Doing a GET with a web login should work with CSRF token on the old backend + Given Logging in using web as "admin" + When Sending a "GET" to "/remote.php/webdav/welcome.txt" with requesttoken + Then Downloaded content should start with "Welcome to your ownCloud account!" + Then the HTTP status code should be "200" + Scenario: Doing a PROPFIND with a web login should not work without CSRF token on the old backend + Given Logging in using web as "admin" + When Sending a "PROPFIND" to "/remote.php/webdav/welcome.txt" without requesttoken + Then the HTTP status code should be "401" + + Scenario: Doing a PROPFIND with a web login should work with CSRF token on the old backend + Given Logging in using web as "admin" + When Sending a "PROPFIND" to "/remote.php/webdav/welcome.txt" with requesttoken + Then the HTTP status code should be "207" |