CertificateManagerTest.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. /**
  3. * Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test\Security;
  9. use OC\Files\Storage\Temporary;
  10. use \OC\Security\CertificateManager;
  11. use OCP\IConfig;
  12. use OCP\ILogger;
  13. /**
  14. * Class CertificateManagerTest
  15. *
  16. * @group DB
  17. */
  18. class CertificateManagerTest extends \Test\TestCase {
  19. use \Test\Traits\UserTrait;
  20. use \Test\Traits\MountProviderTrait;
  21. /** @var CertificateManager */
  22. private $certificateManager;
  23. /** @var String */
  24. private $username;
  25. protected function setUp() {
  26. parent::setUp();
  27. $this->username = $this->getUniqueID('', 20);
  28. $this->createUser($this->username, '');
  29. $storage = new \OC\Files\Storage\Temporary();
  30. $this->registerMount($this->username, $storage, '/' . $this->username . '/');
  31. \OC_Util::tearDownFS();
  32. \OC_User::setUserId('');
  33. \OC\Files\Filesystem::tearDown();
  34. \OC_Util::setupFS($this->username);
  35. $config = $this->createMock(IConfig::class);
  36. $config->expects($this->any())->method('getSystemValue')
  37. ->with('installed', false)->willReturn(true);
  38. $this->certificateManager = new CertificateManager($this->username, new \OC\Files\View(), $config, $this->createMock(ILogger::class));
  39. }
  40. protected function tearDown() {
  41. $user = \OC::$server->getUserManager()->get($this->username);
  42. if ($user !== null) {
  43. $user->delete();
  44. }
  45. parent::tearDown();
  46. }
  47. protected function assertEqualsArrays($expected, $actual) {
  48. sort($expected);
  49. sort($actual);
  50. $this->assertEquals($expected, $actual);
  51. }
  52. function testListCertificates() {
  53. // Test empty certificate bundle
  54. $this->assertSame(array(), $this->certificateManager->listCertificates());
  55. // Add some certificates
  56. $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
  57. $certificateStore = array();
  58. $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
  59. $this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
  60. // Add another certificates
  61. $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
  62. $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
  63. $this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
  64. }
  65. /**
  66. * @expectedException \Exception
  67. * @expectedExceptionMessage Certificate could not get parsed.
  68. */
  69. function testAddInvalidCertificate() {
  70. $this->certificateManager->addCertificate('InvalidCertificate', 'invalidCertificate');
  71. }
  72. /**
  73. * @return array
  74. */
  75. public function dangerousFileProvider() {
  76. return [
  77. ['.htaccess'],
  78. ['../../foo.txt'],
  79. ['..\..\foo.txt'],
  80. ];
  81. }
  82. /**
  83. * @expectedException \Exception
  84. * @expectedExceptionMessage Filename is not valid
  85. * @dataProvider dangerousFileProvider
  86. * @param string $filename
  87. */
  88. function testAddDangerousFile($filename) {
  89. $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), $filename);
  90. }
  91. function testRemoveDangerousFile() {
  92. $this->assertFalse($this->certificateManager->removeCertificate('../../foo.txt'));
  93. }
  94. function testRemoveExistingFile() {
  95. $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
  96. $this->assertTrue($this->certificateManager->removeCertificate('GoodCertificate'));
  97. }
  98. function testGetCertificateBundle() {
  99. $this->assertSame('/' . $this->username . '/files_external/rootcerts.crt', $this->certificateManager->getCertificateBundle());
  100. }
  101. /**
  102. * @dataProvider dataTestNeedRebundling
  103. *
  104. * @param string $uid
  105. * @param int $CaBundleMtime
  106. * @param int $systemWideMtime
  107. * @param int $targetBundleMtime
  108. * @param int $targetBundleExists
  109. * @param bool $expected
  110. */
  111. function testNeedRebundling($uid,
  112. $CaBundleMtime,
  113. $systemWideMtime,
  114. $targetBundleMtime,
  115. $targetBundleExists,
  116. $expected
  117. ) {
  118. $view = $this->getMockBuilder('OC\Files\View')
  119. ->disableOriginalConstructor()->getMock();
  120. $config = $this->createMock(IConfig::class);
  121. /** @var CertificateManager | \PHPUnit_Framework_MockObject_MockObject $certificateManager */
  122. $certificateManager = $this->getMockBuilder('OC\Security\CertificateManager')
  123. ->setConstructorArgs([$uid, $view, $config, $this->createMock(ILogger::class)])
  124. ->setMethods(['getFilemtimeOfCaBundle', 'getCertificateBundle'])
  125. ->getMock();
  126. $certificateManager->expects($this->any())->method('getFilemtimeOfCaBundle')
  127. ->willReturn($CaBundleMtime);
  128. $certificateManager->expects($this->at(1))->method('getCertificateBundle')
  129. ->with($uid)->willReturn('targetBundlePath');
  130. $view->expects($this->any())->method('file_exists')
  131. ->with('targetBundlePath')
  132. ->willReturn($targetBundleExists);
  133. if ($uid !== null && $targetBundleExists) {
  134. $certificateManager->expects($this->at(2))->method('getCertificateBundle')
  135. ->with(null)->willReturn('SystemBundlePath');
  136. }
  137. $view->expects($this->any())->method('filemtime')
  138. ->willReturnCallback(function($path) use ($systemWideMtime, $targetBundleMtime) {
  139. if ($path === 'SystemBundlePath') {
  140. return $systemWideMtime;
  141. } elseif ($path === 'targetBundlePath') {
  142. return $targetBundleMtime;
  143. }
  144. throw new \Exception('unexpected path');
  145. });
  146. $this->assertSame($expected,
  147. $this->invokePrivate($certificateManager, 'needsRebundling', [$uid])
  148. );
  149. }
  150. function dataTestNeedRebundling() {
  151. return [
  152. //values: uid, CaBundleMtime, systemWideMtime, targetBundleMtime, targetBundleExists, expected
  153. // compare minimum of CaBundleMtime and systemWideMtime with targetBundleMtime
  154. ['user1', 10, 20, 30, true, false],
  155. ['user1', 10, 20, 15, true, true],
  156. ['user1', 10, 5, 30, true, false],
  157. ['user1', 10, 5, 8, true, true],
  158. // if no user exists we ignore 'systemWideMtime' because this is the bundle we re-build
  159. [null, 10, 20, 30, true, false],
  160. [null, 10, 20, 15, true, false],
  161. [null, 10, 20, 8, true, true],
  162. [null, 10, 5, 30, true, false],
  163. [null, 10, 5, 8, true, true],
  164. // if no target bundle exists we always build a new one
  165. ['user1', 10, 20, 30, false, true],
  166. ['user1', 10, 20, 15, false, true],
  167. ['user1', 10, 5, 30, false, true],
  168. ['user1', 10, 5, 8, false, true],
  169. [null, 10, 20, 30, false, true],
  170. [null, 10, 20, 15, false, true],
  171. [null, 10, 20, 8, false, true],
  172. [null, 10, 5, 30, false, true],
  173. [null, 10, 5, 8, false, true],
  174. ];
  175. }
  176. }