summaryrefslogtreecommitdiffstats
path: root/tests/lib/Security
diff options
context:
space:
mode:
authorJoas Schilling <nickvergessen@gmx.de>2016-05-20 15:38:20 +0200
committerThomas Müller <DeepDiver1975@users.noreply.github.com>2016-05-20 15:38:20 +0200
commit94ad54ec9b96d41a614fbbad4a97b34c41a6901f (patch)
treef3eb7cdda2704aaf0cd59d58efe66bcbd34cb67d /tests/lib/Security
parent2ef751b1ec28f7b5c7113af60ec8c9fa0ae1cf87 (diff)
downloadnextcloud-server-94ad54ec9b96d41a614fbbad4a97b34c41a6901f.tar.gz
nextcloud-server-94ad54ec9b96d41a614fbbad4a97b34c41a6901f.zip
Move tests/ to PSR-4 (#24731)
* Move a-b to PSR-4 * Move c-d to PSR-4 * Move e+g to PSR-4 * Move h-l to PSR-4 * Move m-r to PSR-4 * Move s-u to PSR-4 * Move files/ to PSR-4 * Move remaining tests to PSR-4 * Remove Test\ from old autoloader
Diffstat (limited to 'tests/lib/Security')
-rw-r--r--tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php69
-rw-r--r--tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php56
-rw-r--r--tests/lib/Security/CSRF/CsrfTokenManagerTest.php136
-rw-r--r--tests/lib/Security/CSRF/CsrfTokenTest.php35
-rw-r--r--tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php109
-rw-r--r--tests/lib/Security/CertificateManagerTest.php121
-rw-r--r--tests/lib/Security/CertificateTest.php111
-rw-r--r--tests/lib/Security/CredentialsManagerTest.php104
-rw-r--r--tests/lib/Security/CryptoTest.php73
-rw-r--r--tests/lib/Security/HasherTest.php118
-rw-r--r--tests/lib/Security/SecureRandomTest.php78
-rw-r--r--tests/lib/Security/TrustedDomainHelperTest.php82
12 files changed, 1092 insertions, 0 deletions
diff --git a/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php b/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php
new file mode 100644
index 00000000000..d463e7c648c
--- /dev/null
+++ b/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Security\CSP;
+
+
+use OC\Security\CSP\ContentSecurityPolicyManager;
+
+class ContentSecurityPolicyManagerTest extends \Test\TestCase {
+ /** @var ContentSecurityPolicyManager */
+ private $contentSecurityPolicyManager;
+
+ public function setUp() {
+ parent::setUp();
+ $this->contentSecurityPolicyManager = new ContentSecurityPolicyManager();
+ }
+
+ public function testAddDefaultPolicy() {
+ $this->contentSecurityPolicyManager->addDefaultPolicy(new \OCP\AppFramework\Http\ContentSecurityPolicy());
+ }
+
+ public function testGetDefaultPolicyWithPolicies() {
+ $policy = new \OCP\AppFramework\Http\ContentSecurityPolicy();
+ $policy->addAllowedFontDomain('mydomain.com');
+ $policy->addAllowedImageDomain('anotherdomain.de');
+ $this->contentSecurityPolicyManager->addDefaultPolicy($policy);
+ $policy = new \OCP\AppFramework\Http\ContentSecurityPolicy();
+ $policy->addAllowedFontDomain('example.com');
+ $policy->addAllowedImageDomain('example.org');
+ $policy->allowInlineScript(true);
+ $this->contentSecurityPolicyManager->addDefaultPolicy($policy);
+ $policy = new \OCP\AppFramework\Http\EmptyContentSecurityPolicy();
+ $policy->addAllowedChildSrcDomain('childdomain');
+ $policy->addAllowedFontDomain('anotherFontDomain');
+ $this->contentSecurityPolicyManager->addDefaultPolicy($policy);
+
+ $expected = new \OC\Security\CSP\ContentSecurityPolicy();
+ $expected->allowInlineScript(true);
+ $expected->addAllowedFontDomain('mydomain.com');
+ $expected->addAllowedFontDomain('example.com');
+ $expected->addAllowedFontDomain('anotherFontDomain');
+ $expected->addAllowedImageDomain('anotherdomain.de');
+ $expected->addAllowedImageDomain('example.org');
+ $expected->addAllowedChildSrcDomain('childdomain');
+ $expectedStringPolicy = 'default-src \'none\';script-src \'self\' \'unsafe-inline\' \'unsafe-eval\';style-src \'self\' \'unsafe-inline\';img-src \'self\' data: blob: anotherdomain.de example.org;font-src \'self\' mydomain.com example.com anotherFontDomain;connect-src \'self\';media-src \'self\';child-src childdomain';
+
+ $this->assertEquals($expected, $this->contentSecurityPolicyManager->getDefaultPolicy());
+ $this->assertSame($expectedStringPolicy, $this->contentSecurityPolicyManager->getDefaultPolicy()->buildPolicy());
+ }
+
+}
diff --git a/tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php b/tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php
new file mode 100644
index 00000000000..28b85c3951f
--- /dev/null
+++ b/tests/lib/Security/CSRF/CsrfTokenGeneratorTest.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Security\CSRF;
+
+class CsrfTokenGeneratorTest extends \Test\TestCase {
+ /** @var \OCP\Security\ISecureRandom */
+ private $random;
+ /** @var \OC\Security\CSRF\CsrfTokenGenerator */
+ private $csrfTokenGenerator;
+
+ public function setUp() {
+ parent::setUp();
+ $this->random = $this->getMockBuilder('\OCP\Security\ISecureRandom')
+ ->disableOriginalConstructor()->getMock();
+ $this->csrfTokenGenerator = new \OC\Security\CSRF\CsrfTokenGenerator($this->random);
+
+ }
+
+ public function testGenerateTokenWithCustomNumber() {
+ $this->random
+ ->expects($this->once())
+ ->method('generate')
+ ->with(3)
+ ->willReturn('abc');
+ $this->assertSame('abc', $this->csrfTokenGenerator->generateToken(3));
+ }
+
+ public function testGenerateTokenWithDefault() {
+ $this->random
+ ->expects($this->once())
+ ->method('generate')
+ ->with(32)
+ ->willReturn('12345678901234567890123456789012');
+ $this->assertSame('12345678901234567890123456789012', $this->csrfTokenGenerator->generateToken(32));
+ }
+}
+
diff --git a/tests/lib/Security/CSRF/CsrfTokenManagerTest.php b/tests/lib/Security/CSRF/CsrfTokenManagerTest.php
new file mode 100644
index 00000000000..ab19a43e91e
--- /dev/null
+++ b/tests/lib/Security/CSRF/CsrfTokenManagerTest.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Security\CSRF;
+
+class CsrfTokenManagerTest extends \Test\TestCase {
+ /** @var \OC\Security\CSRF\CsrfTokenManager */
+ private $csrfTokenManager;
+ /** @var \OC\Security\CSRF\CsrfTokenGenerator */
+ private $tokenGenerator;
+ /** @var \OC\Security\CSRF\TokenStorage\SessionStorage */
+ private $storageInterface;
+
+ public function setUp() {
+ parent::setUp();
+ $this->tokenGenerator = $this->getMockBuilder('\OC\Security\CSRF\CsrfTokenGenerator')
+ ->disableOriginalConstructor()->getMock();
+ $this->storageInterface = $this->getMockBuilder('\OC\Security\CSRF\TokenStorage\SessionStorage')
+ ->disableOriginalConstructor()->getMock();
+
+ $this->csrfTokenManager = new \OC\Security\CSRF\CsrfTokenManager(
+ $this->tokenGenerator,
+ $this->storageInterface
+ );
+ }
+
+ public function testGetTokenWithExistingToken() {
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('hasToken')
+ ->willReturn(true);
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('getToken')
+ ->willReturn('MyExistingToken');
+
+ $expected = new \OC\Security\CSRF\CsrfToken('MyExistingToken');
+ $this->assertEquals($expected, $this->csrfTokenManager->getToken());
+ }
+
+ public function testGetTokenWithoutExistingToken() {
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('hasToken')
+ ->willReturn(false);
+ $this->tokenGenerator
+ ->expects($this->once())
+ ->method('generateToken')
+ ->willReturn('MyNewToken');
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('setToken')
+ ->with('MyNewToken');
+
+ $expected = new \OC\Security\CSRF\CsrfToken('MyNewToken');
+ $this->assertEquals($expected, $this->csrfTokenManager->getToken());
+ }
+
+ public function testRefreshToken() {
+ $this->tokenGenerator
+ ->expects($this->once())
+ ->method('generateToken')
+ ->willReturn('MyNewToken');
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('setToken')
+ ->with('MyNewToken');
+
+ $expected = new \OC\Security\CSRF\CsrfToken('MyNewToken');
+ $this->assertEquals($expected, $this->csrfTokenManager->refreshToken());
+ }
+
+ public function testRemoveToken() {
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('removeToken');
+
+ $this->csrfTokenManager->removeToken();
+ }
+
+ public function testIsTokenValidWithoutToken() {
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('hasToken')
+ ->willReturn(false);
+ $token = new \OC\Security\CSRF\CsrfToken('Token');
+
+ $this->assertSame(false, $this->csrfTokenManager->isTokenValid($token));
+ }
+
+ public function testIsTokenValidWithWrongToken() {
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('hasToken')
+ ->willReturn(true);
+ $token = new \OC\Security\CSRF\CsrfToken('Token');
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('getToken')
+ ->willReturn('MyToken');
+
+ $this->assertSame(false, $this->csrfTokenManager->isTokenValid($token));
+ }
+
+ public function testIsTokenValidWithValidToken() {
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('hasToken')
+ ->willReturn(true);
+ $token = new \OC\Security\CSRF\CsrfToken('XlQhHjgWCgBXAEI0Khl+IQEiCXN2LUcDHAQTQAc1HQs=:qgkUlg8l3m8WnkOG4XM9Az33pAt1vSVMx4hcJFsxdqc=');
+ $this->storageInterface
+ ->expects($this->once())
+ ->method('getToken')
+ ->willReturn('/3JKTq2ldmzcDr1f5zDJ7Wt0lEgqqfKF');
+
+ $this->assertSame(true, $this->csrfTokenManager->isTokenValid($token));
+ }
+}
diff --git a/tests/lib/Security/CSRF/CsrfTokenTest.php b/tests/lib/Security/CSRF/CsrfTokenTest.php
new file mode 100644
index 00000000000..da640ce5052
--- /dev/null
+++ b/tests/lib/Security/CSRF/CsrfTokenTest.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Security\CSRF;
+
+class CsrfTokenTest extends \Test\TestCase {
+ public function testGetEncryptedValue() {
+ $csrfToken = new \OC\Security\CSRF\CsrfToken('MyCsrfToken');
+ $this->assertSame(33, strlen($csrfToken->getEncryptedValue()));
+ $this->assertSame(':', $csrfToken->getEncryptedValue()[16]);
+ }
+
+ public function testGetDecryptedValue() {
+ $csrfToken = new \OC\Security\CSRF\CsrfToken('XlQhHjgWCgBXAEI0Khl+IQEiCXN2LUcDHAQTQAc1HQs=:qgkUlg8l3m8WnkOG4XM9Az33pAt1vSVMx4hcJFsxdqc=');
+ $this->assertSame('/3JKTq2ldmzcDr1f5zDJ7Wt0lEgqqfKF', $csrfToken->getDecryptedValue());
+ }
+}
diff --git a/tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php b/tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php
new file mode 100644
index 00000000000..550fa49e1b2
--- /dev/null
+++ b/tests/lib/Security/CSRF/TokenStorage/SessionStorageTest.php
@@ -0,0 +1,109 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Security\CSRF\TokenStorage;
+
+class SessionStorageTest extends \Test\TestCase {
+ /** @var \OCP\ISession */
+ private $session;
+ /** @var \OC\Security\CSRF\TokenStorage\SessionStorage */
+ private $sessionStorage;
+
+ public function setUp() {
+ parent::setUp();
+ $this->session = $this->getMockBuilder('\OCP\ISession')
+ ->disableOriginalConstructor()->getMock();
+ $this->sessionStorage = new \OC\Security\CSRF\TokenStorage\SessionStorage($this->session);
+ }
+
+ /**
+ * @return array
+ */
+ public function getTokenDataProvider() {
+ return [
+ [
+ '',
+ ],
+ [
+ null,
+ ],
+ ];
+ }
+
+ /**
+ * @param string $token
+ * @dataProvider getTokenDataProvider
+ *
+ * @expectedException \Exception
+ * @expectedExceptionMessage Session does not contain a requesttoken
+ */
+ public function testGetTokenWithEmptyToken($token) {
+ $this->session
+ ->expects($this->once())
+ ->method('get')
+ ->with('requesttoken')
+ ->willReturn($token);
+ $this->sessionStorage->getToken();
+ }
+
+ public function testGetTokenWithValidToken() {
+ $this->session
+ ->expects($this->once())
+ ->method('get')
+ ->with('requesttoken')
+ ->willReturn('MyFancyCsrfToken');
+ $this->assertSame('MyFancyCsrfToken', $this->sessionStorage->getToken());
+ }
+
+ public function testSetToken() {
+ $this->session
+ ->expects($this->once())
+ ->method('set')
+ ->with('requesttoken', 'TokenToSet');
+ $this->sessionStorage->setToken('TokenToSet');
+ }
+
+ public function testRemoveToken() {
+ $this->session
+ ->expects($this->once())
+ ->method('remove')
+ ->with('requesttoken');
+ $this->sessionStorage->removeToken();
+ }
+
+ public function testHasTokenWithExistingToken() {
+ $this->session
+ ->expects($this->once())
+ ->method('exists')
+ ->with('requesttoken')
+ ->willReturn(true);
+ $this->assertSame(true, $this->sessionStorage->hasToken());
+ }
+
+ public function testHasTokenWithoutExistingToken() {
+ $this->session
+ ->expects($this->once())
+ ->method('exists')
+ ->with('requesttoken')
+ ->willReturn(false);
+ $this->assertSame(false, $this->sessionStorage->hasToken());
+ }
+}
diff --git a/tests/lib/Security/CertificateManagerTest.php b/tests/lib/Security/CertificateManagerTest.php
new file mode 100644
index 00000000000..43206569cf4
--- /dev/null
+++ b/tests/lib/Security/CertificateManagerTest.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Copyright (c) 2014 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\Security;
+
+use \OC\Security\CertificateManager;
+
+/**
+ * Class CertificateManagerTest
+ *
+ * @group DB
+ */
+class CertificateManagerTest extends \Test\TestCase {
+ use \Test\Traits\UserTrait;
+ use \Test\Traits\MountProviderTrait;
+
+ /** @var CertificateManager */
+ private $certificateManager;
+ /** @var String */
+ private $username;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->username = $this->getUniqueID('', 20);
+ $this->createUser($this->username, '');
+
+ $storage = new \OC\Files\Storage\Temporary();
+ $this->registerMount($this->username, $storage, '/' . $this->username . '/');
+
+ \OC_Util::tearDownFS();
+ \OC_User::setUserId('');
+ \OC\Files\Filesystem::tearDown();
+ \OC_Util::setupFS($this->username);
+
+ $config = $this->getMock('OCP\IConfig');
+ $config->expects($this->any())->method('getSystemValue')
+ ->with('installed', false)->willReturn(true);
+
+ $this->certificateManager = new CertificateManager($this->username, new \OC\Files\View(), $config);
+ }
+
+ protected function tearDown() {
+ $user = \OC::$server->getUserManager()->get($this->username);
+ if ($user !== null) {
+ $user->delete();
+ }
+ parent::tearDown();
+ }
+
+ protected function assertEqualsArrays($expected, $actual) {
+ sort($expected);
+ sort($actual);
+
+ $this->assertEquals($expected, $actual);
+ }
+
+ function testListCertificates() {
+ // Test empty certificate bundle
+ $this->assertSame(array(), $this->certificateManager->listCertificates());
+
+ // Add some certificates
+ $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
+ $certificateStore = array();
+ $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
+ $this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
+
+ // Add another certificates
+ $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
+ $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
+ $this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Certificate could not get parsed.
+ */
+ function testAddInvalidCertificate() {
+ $this->certificateManager->addCertificate('InvalidCertificate', 'invalidCertificate');
+ }
+
+ /**
+ * @return array
+ */
+ public function dangerousFileProvider() {
+ return [
+ ['.htaccess'],
+ ['../../foo.txt'],
+ ['..\..\foo.txt'],
+ ];
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Filename is not valid
+ * @dataProvider dangerousFileProvider
+ * @param string $filename
+ */
+ function testAddDangerousFile($filename) {
+ $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), $filename);
+ }
+
+ function testRemoveDangerousFile() {
+ $this->assertFalse($this->certificateManager->removeCertificate('../../foo.txt'));
+ }
+
+ function testRemoveExistingFile() {
+ $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
+ $this->assertTrue($this->certificateManager->removeCertificate('GoodCertificate'));
+ }
+
+ function testGetCertificateBundle() {
+ $this->assertSame('/' . $this->username . '/files_external/rootcerts.crt', $this->certificateManager->getCertificateBundle());
+ }
+
+}
diff --git a/tests/lib/Security/CertificateTest.php b/tests/lib/Security/CertificateTest.php
new file mode 100644
index 00000000000..6f7d7d4a37f
--- /dev/null
+++ b/tests/lib/Security/CertificateTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Security;
+
+use \OC\Security\Certificate;
+
+class CertificateTest extends \Test\TestCase {
+
+ /** @var Certificate That contains a valid certificate */
+ protected $goodCertificate;
+ /** @var Certificate That contains an invalid certificate */
+ protected $invalidCertificate;
+ /** @var Certificate That contains an expired certificate */
+ protected $expiredCertificate;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $goodCertificate = file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt');
+ $this->goodCertificate = new Certificate($goodCertificate, 'GoodCertificate');
+ $badCertificate = file_get_contents(__DIR__ . '/../../data/certificates/badCertificate.crt');
+ $this->invalidCertificate = new Certificate($badCertificate, 'BadCertificate');
+ $expiredCertificate = file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt');
+ $this->expiredCertificate = new Certificate($expiredCertificate, 'ExpiredCertificate');
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Certificate could not get parsed.
+ */
+ public function testBogusData() {
+ $certificate = new Certificate('foo', 'bar');
+ $certificate->getIssueDate();
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Certificate could not get parsed.
+ */
+ function testCertificateStartingWithFileReference() {
+ new Certificate('file://'.__DIR__ . '/../../data/certificates/goodCertificate.crt', 'bar');
+ }
+
+ public function testGetName() {
+ $this->assertSame('GoodCertificate', $this->goodCertificate->getName());
+ $this->assertSame('BadCertificate', $this->invalidCertificate->getName());
+ }
+
+ public function testGetCommonName() {
+ $this->assertSame('security.owncloud.com', $this->goodCertificate->getCommonName());
+ $this->assertSame(null, $this->invalidCertificate->getCommonName());
+ }
+
+ public function testGetOrganization() {
+ $this->assertSame('ownCloud Security', $this->goodCertificate->getOrganization());
+ $this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getOrganization());
+ }
+
+ public function testGetIssueDate() {
+ $expected = new \DateTime('2015-08-27 20:03:42 GMT');
+ $this->assertEquals($expected->getTimestamp(), $this->goodCertificate->getIssueDate()->getTimestamp());
+ $expected = new \DateTime('2015-08-27 20:19:13 GMT');
+ $this->assertEquals($expected->getTimestamp(), $this->invalidCertificate->getIssueDate()->getTimestamp());
+ }
+
+ public function testGetExpireDate() {
+ $expected = new \DateTime('2025-08-24 20:03:42 GMT');
+ $this->assertEquals($expected->getTimestamp(), $this->goodCertificate->getExpireDate()->getTimestamp());
+ $expected = new \DateTime('2025-08-24 20:19:13 GMT');
+ $this->assertEquals($expected->getTimestamp(), $this->invalidCertificate->getExpireDate()->getTimestamp());
+ $expected = new \DateTime('2014-08-28 09:12:43 GMT');
+ $this->assertEquals($expected->getTimestamp(), $this->expiredCertificate->getExpireDate()->getTimestamp());
+ }
+
+ public function testIsExpired() {
+ $this->assertSame(false, $this->goodCertificate->isExpired());
+ $this->assertSame(false, $this->invalidCertificate->isExpired());
+ $this->assertSame(true, $this->expiredCertificate->isExpired());
+ }
+
+ public function testGetIssuerName() {
+ $this->assertSame('security.owncloud.com', $this->goodCertificate->getIssuerName());
+ $this->assertSame(null, $this->invalidCertificate->getIssuerName());
+ $this->assertSame(null, $this->expiredCertificate->getIssuerName());
+ }
+
+ public function testGetIssuerOrganization() {
+ $this->assertSame('ownCloud Security', $this->goodCertificate->getIssuerOrganization());
+ $this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getIssuerOrganization());
+ $this->assertSame('Internet Widgits Pty Ltd', $this->expiredCertificate->getIssuerOrganization());
+ }
+}
diff --git a/tests/lib/Security/CredentialsManagerTest.php b/tests/lib/Security/CredentialsManagerTest.php
new file mode 100644
index 00000000000..7eb4e4d7b1a
--- /dev/null
+++ b/tests/lib/Security/CredentialsManagerTest.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Security;
+
+use \OCP\Security\ICrypto;
+use \OCP\IDBConnection;
+use \OC\Security\CredentialsManager;
+
+class CredentialsManagerTest extends \Test\TestCase {
+
+ /** @var ICrypto */
+ protected $crypto;
+
+ /** @var IDBConnection */
+ protected $dbConnection;
+
+ /** @var CredentialsManager */
+ protected $manager;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->crypto = $this->getMock('\OCP\Security\ICrypto');
+ $this->dbConnection = $this->getMockBuilder('\OC\DB\Connection')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->manager = new CredentialsManager($this->crypto, $this->dbConnection);
+ }
+
+ private function getQeuryResult($row) {
+ $result = $this->getMockBuilder('\Doctrine\DBAL\Driver\Statement')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result->expects($this->any())
+ ->method('fetch')
+ ->will($this->returnValue($row));
+
+ return $result;
+ }
+
+ public function testStore() {
+ $userId = 'abc';
+ $identifier = 'foo';
+ $credentials = 'bar';
+
+ $this->crypto->expects($this->once())
+ ->method('encrypt')
+ ->with(json_encode($credentials))
+ ->willReturn('baz');
+
+ $this->dbConnection->expects($this->once())
+ ->method('setValues')
+ ->with(CredentialsManager::DB_TABLE,
+ ['user' => $userId, 'identifier' => $identifier],
+ ['credentials' => 'baz']
+ );
+
+ $this->manager->store($userId, $identifier, $credentials);
+ }
+
+ public function testRetrieve() {
+ $userId = 'abc';
+ $identifier = 'foo';
+
+ $this->crypto->expects($this->once())
+ ->method('decrypt')
+ ->with('baz')
+ ->willReturn(json_encode('bar'));
+
+ $qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder')
+ ->setConstructorArgs([$this->dbConnection])
+ ->setMethods(['execute'])
+ ->getMock();
+ $qb->expects($this->once())
+ ->method('execute')
+ ->willReturn($this->getQeuryResult(['credentials' => 'baz']));
+
+ $this->dbConnection->expects($this->once())
+ ->method('getQueryBuilder')
+ ->willReturn($qb);
+
+ $this->manager->retrieve($userId, $identifier);
+ }
+
+}
diff --git a/tests/lib/Security/CryptoTest.php b/tests/lib/Security/CryptoTest.php
new file mode 100644
index 00000000000..356d504f4b3
--- /dev/null
+++ b/tests/lib/Security/CryptoTest.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright (c) 2014 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\Security;
+
+use \OC\Security\Crypto;
+
+class CryptoTest extends \Test\TestCase {
+
+ public function defaultEncryptionProvider()
+ {
+ return array(
+ array('Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'),
+ array(''),
+ array('我看这本书。 我看這本書')
+ );
+ }
+
+ /** @var Crypto */
+ protected $crypto;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->crypto = new Crypto(\OC::$server->getConfig(), \OC::$server->getSecureRandom());
+ }
+
+ /**
+ * @dataProvider defaultEncryptionProvider
+ */
+ function testDefaultEncrypt($stringToEncrypt) {
+ $ciphertext = $this->crypto->encrypt($stringToEncrypt);
+ $this->assertEquals($stringToEncrypt, $this->crypto->decrypt($ciphertext));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage HMAC does not match.
+ */
+ function testWrongPassword() {
+ $stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.';
+ $ciphertext = $this->crypto->encrypt($stringToEncrypt);
+ $this->crypto->decrypt($ciphertext, 'A wrong password!');
+ }
+
+ function testLaterDecryption() {
+ $stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.';
+ $encryptedString = '44a35023cca2e7a6125e06c29fc4b2ad9d8a33d0873a8b45b0de4ef9284f260c6c46bf25dc62120644c59b8bafe4281ddc47a70c35ae6c29ef7a63d79eefacc297e60b13042ac582733598d0a6b4de37311556bb5c480fd2633de4e6ebafa868c2d1e2d80a5d24f9660360dba4d6e0c8|lhrFgK0zd9U160Wo|a75e57ab701f9124e1113543fd1dc596f21e20d456a0d1e813d5a8aaec9adcb11213788e96598b67fe9486a9f0b99642c18296d0175db44b1ae426e4e91080ee';
+ $this->assertEquals($stringToEncrypt, $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd'));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage HMAC does not match.
+ */
+ function testWrongIV() {
+ $encryptedString = '560f5436ba864b9f12f7f7ca6d41c327554a6f2c0a160a03316b202af07c65163274993f3a46e7547c07ba89304f00594a2f3bd99f83859097c58049c39d0d4ade10e0de914ff0604961e7c849d0271ed6c0b23f984ba16e7d033e3305fb0910e7b6a2a65c988d17dbee71d8f953684d|d2kdFUspVjC0o0sr|1a5feacf87eaa6869a6abdfba9a296e7bbad45b6ad89f7dce67cdc98e2da5dc4379cc672cc655e52bbf19599bf59482fbea13a73937697fa656bf10f3fc4f1aa';
+ $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd');
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Authenticated ciphertext could not be decoded.
+ */
+ function testWrongParameters() {
+ $encryptedString = '1|2';
+ $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd');
+ }
+}
diff --git a/tests/lib/Security/HasherTest.php b/tests/lib/Security/HasherTest.php
new file mode 100644
index 00000000000..913f4d703e8
--- /dev/null
+++ b/tests/lib/Security/HasherTest.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Copyright (c) 2014 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\Security;
+
+use OC\Security\Hasher;
+
+/**
+ * Class HasherTest
+ */
+class HasherTest extends \Test\TestCase {
+
+ /**
+ * @return array
+ */
+ public function versionHashProvider()
+ {
+ return array(
+ array('asf32äà$$a.|3', null),
+ array('asf32äà$$a.|3|5', null),
+ array('1|2|3|4', array('version' => 1, 'hash' => '2|3|4')),
+ array('1|我看|这本书。 我看這本書', array('version' => 1, 'hash' => '我看|这本书。 我看這本書'))
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function allHashProviders()
+ {
+ return array(
+ // Bogus values
+ array(null, 'asf32äà$$a.|3', false),
+ array(null, false, false),
+
+ // Valid SHA1 strings
+ array('password', '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', true),
+ array('owncloud.com', '27a4643e43046c3569e33b68c1a4b15d31306d29', true),
+
+ // Invalid SHA1 strings
+ array('InvalidString', '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', false),
+ array('AnotherInvalidOne', '27a4643e43046c3569e33b68c1a4b15d31306d29', false),
+
+ // Valid legacy password string with password salt "6Wow67q1wZQZpUUeI6G2LsWUu4XKx"
+ array('password', '$2a$08$emCpDEl.V.QwPWt5gPrqrOhdpH6ailBmkj2Hd2vD5U8qIy20HBe7.', true),
+ array('password', '$2a$08$yjaLO4ev70SaOsWZ9gRS3eRSEpHVsmSWTdTms1949mylxJ279hzo2', true),
+ array('password', '$2a$08$.jNRG/oB4r7gHJhAyb.mDupNUAqTnBIW/tWBqFobaYflKXiFeG0A6', true),
+ array('owncloud.com', '$2a$08$YbEsyASX/hXVNMv8hXQo7ezreN17T8Jl6PjecGZvpX.Ayz2aUyaZ2', true),
+ array('owncloud.com', '$2a$11$cHdDA2IkUP28oNGBwlL7jO/U3dpr8/0LIjTZmE8dMPA7OCUQsSTqS', true),
+ array('owncloud.com', '$2a$08$GH.UoIfJ1e.qeZ85KPqzQe6NR8XWRgJXWIUeE1o/j1xndvyTA1x96', true),
+
+ // Invalid legacy passwords
+ array('password', '$2a$08$oKAQY5IhnZocP.61MwP7xu7TNeOb7Ostvk3j6UpacvaNMs.xRj7O2', false),
+
+ // Valid passwords "6Wow67q1wZQZpUUeI6G2LsWUu4XKx"
+ array('password', '1|$2a$05$ezAE0dkwk57jlfo6z5Pql.gcIK3ReXT15W7ITNxVS0ksfhO/4E4Kq', true),
+ array('password', '1|$2a$05$4OQmloFW4yTVez2MEWGIleDO9Z5G9tWBXxn1vddogmKBQq/Mq93pe', true),
+ array('password', '1|$2a$11$yj0hlp6qR32G9exGEXktB.yW2rgt2maRBbPgi3EyxcDwKrD14x/WO', true),
+ array('owncloud.com', '1|$2a$10$Yiss2WVOqGakxuuqySv5UeOKpF8d8KmNjuAPcBMiRJGizJXjA2bKm', true),
+ array('owncloud.com', '1|$2a$10$v9mh8/.mF/Ut9jZ7pRnpkuac3bdFCnc4W/gSumheQUi02Sr.xMjPi', true),
+ array('owncloud.com', '1|$2a$05$ST5E.rplNRfDCzRpzq69leRzsTGtY7k88h9Vy2eWj0Ug/iA9w5kGK', true),
+
+ // Invalid passwords
+ array('password', '0|$2a$08$oKAQY5IhnZocP.61MwP7xu7TNeOb7Ostvk3j6UpacvaNMs.xRj7O2', false),
+ array('password', '1|$2a$08$oKAQY5IhnZocP.61MwP7xu7TNeOb7Ostvk3j6UpacvaNMs.xRj7O2', false),
+ array('password', '2|$2a$08$oKAQY5IhnZocP.61MwP7xu7TNeOb7Ostvk3j6UpacvaNMs.xRj7O2', false),
+ );
+ }
+
+ /** @var Hasher */
+ protected $hasher;
+
+ /** @var \OCP\IConfig */
+ protected $config;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->config = $this->getMockBuilder('\OCP\IConfig')
+ ->disableOriginalConstructor()->getMock();
+
+ $this->hasher = new Hasher($this->config);
+ }
+
+ function testHash() {
+ $hash = $this->hasher->hash('String To Hash');
+ $this->assertNotNull($hash);
+ }
+
+ /**
+ * @dataProvider versionHashProvider
+ */
+ function testSplitHash($hash, $expected) {
+ $relativePath = self::invokePrivate($this->hasher, 'splitHash', array($hash));
+ $this->assertSame($expected, $relativePath);
+ }
+
+
+ /**
+ * @dataProvider allHashProviders
+ */
+ function testVerify($password, $hash, $expected) {
+ $this->config
+ ->expects($this->any())
+ ->method('getSystemValue')
+ ->with('passwordsalt', null)
+ ->will($this->returnValue('6Wow67q1wZQZpUUeI6G2LsWUu4XKx'));
+
+ $result = $this->hasher->verify($password, $hash);
+ $this->assertSame($expected, $result);
+ }
+
+}
diff --git a/tests/lib/Security/SecureRandomTest.php b/tests/lib/Security/SecureRandomTest.php
new file mode 100644
index 00000000000..40431c89795
--- /dev/null
+++ b/tests/lib/Security/SecureRandomTest.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Copyright (c) 2014 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\Security;
+
+use \OC\Security\SecureRandom;
+
+class SecureRandomTest extends \Test\TestCase {
+
+ public function stringGenerationProvider() {
+ return array(
+ array(0, 0),
+ array(1, 1),
+ array(128, 128),
+ array(256, 256),
+ array(1024, 1024),
+ array(2048, 2048),
+ array(64000, 64000),
+ );
+ }
+
+ public static function charCombinations() {
+ return array(
+ array('CHAR_LOWER', '[a-z]'),
+ array('CHAR_UPPER', '[A-Z]'),
+ array('CHAR_DIGITS', '[0-9]'),
+ );
+ }
+
+ /** @var SecureRandom */
+ protected $rng;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->rng = new \OC\Security\SecureRandom();
+ }
+
+ /**
+ * @dataProvider stringGenerationProvider
+ */
+ function testGetLowStrengthGeneratorLength($length, $expectedLength) {
+ $generator = $this->rng;
+
+ $this->assertEquals($expectedLength, strlen($generator->generate($length)));
+ }
+
+ /**
+ * @dataProvider stringGenerationProvider
+ */
+ function testMediumLowStrengthGeneratorLength($length, $expectedLength) {
+ $generator = $this->rng;
+
+ $this->assertEquals($expectedLength, strlen($generator->generate($length)));
+ }
+
+ /**
+ * @dataProvider stringGenerationProvider
+ */
+ function testUninitializedGenerate($length, $expectedLength) {
+ $this->assertEquals($expectedLength, strlen($this->rng->generate($length)));
+ }
+
+ /**
+ * @dataProvider charCombinations
+ */
+ public function testScheme($charName, $chars) {
+ $generator = $this->rng;
+ $scheme = constant('OCP\Security\ISecureRandom::' . $charName);
+ $randomString = $generator->generate(100, $scheme);
+ $matchesRegex = preg_match('/^'.$chars.'+$/', $randomString);
+ $this->assertSame(1, $matchesRegex);
+ }
+}
diff --git a/tests/lib/Security/TrustedDomainHelperTest.php b/tests/lib/Security/TrustedDomainHelperTest.php
new file mode 100644
index 00000000000..dfd51167cca
--- /dev/null
+++ b/tests/lib/Security/TrustedDomainHelperTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * 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.
+ */
+
+namespace Test\Security;
+
+use \OC\Security\TrustedDomainHelper;
+use OCP\IConfig;
+
+/**
+ * Class TrustedDomainHelperTest
+ */
+class TrustedDomainHelperTest extends \Test\TestCase {
+ /** @var IConfig */
+ protected $config;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->config = $this->getMockBuilder('\OCP\IConfig')->getMock();
+ }
+
+ /**
+ * @dataProvider trustedDomainDataProvider
+ * @param string $trustedDomains
+ * @param string $testDomain
+ * @param bool $result
+ */
+ public function testIsTrustedDomain($trustedDomains, $testDomain, $result) {
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('trusted_domains')
+ ->will($this->returnValue($trustedDomains));
+
+ $trustedDomainHelper = new TrustedDomainHelper($this->config);
+ $this->assertEquals($result, $trustedDomainHelper->isTrustedDomain($testDomain));
+ }
+
+ /**
+ * @return array
+ */
+ public function trustedDomainDataProvider() {
+ $trustedHostTestList = [
+ 'host.one.test',
+ 'host.two.test',
+ '[1fff:0:a88:85a3::ac1f]',
+ 'host.three.test:443',
+ ];
+ return [
+ // empty defaults to false with 8.1
+ [null, 'host.one.test:8080', false],
+ ['', 'host.one.test:8080', false],
+ [[], 'host.one.test:8080', false],
+ // trust list when defined
+ [$trustedHostTestList, 'host.two.test:8080', true],
+ [$trustedHostTestList, 'host.two.test:9999', true],
+ [$trustedHostTestList, 'host.three.test:8080', false],
+ [$trustedHostTestList, 'host.two.test:8080:aa:222', false],
+ [$trustedHostTestList, '[1fff:0:a88:85a3::ac1f]', true],
+ [$trustedHostTestList, '[1fff:0:a88:85a3::ac1f]:801', true],
+ [$trustedHostTestList, '[1fff:0:a88:85a3::ac1f]:801:34', false],
+ [$trustedHostTestList, 'host.three.test:443', true],
+ [$trustedHostTestList, 'host.three.test:80', false],
+ [$trustedHostTestList, 'host.three.test', false],
+ // trust localhost regardless of trust list
+ [$trustedHostTestList, 'localhost', true],
+ [$trustedHostTestList, 'localhost:8080', true],
+ [$trustedHostTestList, '127.0.0.1', true],
+ [$trustedHostTestList, '127.0.0.1:8080', true],
+ // do not trust invalid localhosts
+ [$trustedHostTestList, 'localhost:1:2', false],
+ [$trustedHostTestList, 'localhost: evil.host', false],
+ // do not trust casting
+ [[1], '1', false],
+ ];
+ }
+
+}