1
0

CheckerTest.php 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422
  1. <?php
  2. /**
  3. * @author Lukas Reschke <lukas@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2015, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace Test\IntegrityCheck;
  22. use OC\IntegrityCheck\Checker;
  23. use OC\IntegrityCheck\Helpers\AppLocator;
  24. use OC\IntegrityCheck\Helpers\EnvironmentHelper;
  25. use OC\IntegrityCheck\Helpers\FileAccessHelper;
  26. use OC\Memcache\NullCache;
  27. use OCP\App\IAppManager;
  28. use OCP\ICacheFactory;
  29. use OCP\IConfig;
  30. use phpseclib\Crypt\RSA;
  31. use phpseclib\File\X509;
  32. use Test\TestCase;
  33. class CheckerTest extends TestCase {
  34. /** @var EnvironmentHelper|\PHPUnit\Framework\MockObject\MockObject */
  35. private $environmentHelper;
  36. /** @var AppLocator|\PHPUnit\Framework\MockObject\MockObject */
  37. private $appLocator;
  38. /** @var Checker */
  39. private $checker;
  40. /** @var FileAccessHelper|\PHPUnit\Framework\MockObject\MockObject */
  41. private $fileAccessHelper;
  42. /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
  43. private $config;
  44. /** @var ICacheFactory|\PHPUnit\Framework\MockObject\MockObject */
  45. private $cacheFactory;
  46. /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
  47. private $appManager;
  48. /** @var \OC\Files\Type\Detection|\PHPUnit\Framework\MockObject\MockObject */
  49. private $mimeTypeDetector;
  50. protected function setUp(): void {
  51. parent::setUp();
  52. $this->environmentHelper = $this->createMock(EnvironmentHelper::class);
  53. $this->fileAccessHelper = $this->createMock(FileAccessHelper::class);
  54. $this->appLocator = $this->createMock(AppLocator::class);
  55. $this->config = $this->createMock(IConfig::class);
  56. $this->cacheFactory = $this->createMock(ICacheFactory::class);
  57. $this->appManager = $this->createMock(IAppManager::class);
  58. $this->mimeTypeDetector = $this->createMock(\OC\Files\Type\Detection::class);
  59. $this->config->method('getAppValue')
  60. ->willReturnArgument(2);
  61. $this->cacheFactory
  62. ->expects($this->any())
  63. ->method('createDistributed')
  64. ->with('oc.integritycheck.checker')
  65. ->willReturn(new NullCache());
  66. $this->checker = new Checker(
  67. $this->environmentHelper,
  68. $this->fileAccessHelper,
  69. $this->appLocator,
  70. $this->config,
  71. $this->cacheFactory,
  72. $this->appManager,
  73. $this->mimeTypeDetector
  74. );
  75. }
  76. public function testWriteAppSignatureOfNotExistingApp() {
  77. $this->expectException(\Exception::class);
  78. $this->expectExceptionMessage('Exception message');
  79. $this->fileAccessHelper
  80. ->expects($this->at(0))
  81. ->method('assertDirectoryExists')
  82. ->with('NotExistingApp/appinfo')
  83. ->willThrowException(new \Exception('Exception message'));
  84. $this->fileAccessHelper
  85. ->expects($this->at(1))
  86. ->method('is_writable')
  87. ->with('NotExistingApp/appinfo')
  88. ->willReturn(true);
  89. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
  90. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
  91. $rsa = new RSA();
  92. $rsa->loadKey($rsaPrivateKey);
  93. $x509 = new X509();
  94. $x509->loadX509($keyBundle);
  95. $this->checker->writeAppSignature('NotExistingApp', $x509, $rsa);
  96. }
  97. public function testWriteAppSignatureWrongPermissions() {
  98. $this->expectException(\Exception::class);
  99. $this->expectExceptionMessageMatches('/[a-zA-Z\\/_-]+ is not writable/');
  100. $this->fileAccessHelper
  101. ->expects($this->once())
  102. ->method('file_put_contents')
  103. ->will($this->throwException(new \Exception('Exception message')));
  104. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
  105. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
  106. $rsa = new RSA();
  107. $rsa->loadKey($rsaPrivateKey);
  108. $x509 = new X509();
  109. $x509->loadX509($keyBundle);
  110. $this->checker->writeAppSignature(\OC::$SERVERROOT . '/tests/data/integritycheck/app/', $x509, $rsa);
  111. }
  112. public function testWriteAppSignature() {
  113. $expectedSignatureFileData = '{
  114. "hashes": {
  115. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  116. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  117. },
  118. "signature": "Y5yvXvcGHVPuRRatKVDUONWq1FpLXugZd6Km\/+aEHsQj7coVl9FeMj9OsWamBf7yRIw3dtNLguTLlAA9QAv\/b0uHN3JnbNZN+dwFOve4NMtqXfSDlWftqKN00VS+RJXpG1S2IIx9Poyp2NoghL\/5AuTv4GHiNb7zU\/DT\/kt71pUGPgPR6IIFaE+zHOD96vjYkrH+GfWZzKR0FCdLib9yyNvk+EGrcjKM6qjs2GKfS\/XFjj\/\/neDnh\/0kcPuKE3ZbofnI4TIDTv0CGqvOp7PtqVNc3Vy\/UKa7uF1PT0MAUKMww6EiMUSFZdUVP4WWF0Y72W53Qdtf1hrAZa2kfKyoK5kd7sQmCSKUPSU8978AUVZlBtTRlyT803IKwMV0iHMkw+xYB1sN2FlHup\/DESADqxhdgYuK35bCPvgkb4SBe4B8Voz\/izTvcP7VT5UvkYdAO+05\/jzdaHEmzmsD92CFfvX0q8O\/Y\/29ubftUJsqcHeMDKgcR4eZOE8+\/QVc\/89QO6WnKNuNuV+5bybO6g6PAdC9ZPsCvnihS61O2mwRXHLR3jv2UleFWm+lZEquPKtkhi6SLtDiijA4GV6dmS+dzujSLb7hGeD5o1plZcZ94uhWljl+QIp82+zU\/lYB1Zfr4Mb4e+V7r2gv7Fbv7y6YtjE2GIQwRhC5jq56bD0ZB+I=",
  119. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEwTCCAqmgAwIBAgIUWv0iujufs5lUr0svCf\/qTQvoyKAwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIyNDk1M1oXDTE2MTEwMzIyNDk1M1owEjEQMA4GA1UEAwwHU29tZUFwcDCCAiIw\r\nDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK8q0x62agGSRBqeWsaeEwFfepMk\r\nF8cAobMMi50qHCv9IrOn\/ZH9l52xBrbIkErVmRjmly0d4JhD8Ymhidsh9ONKYl\/j\r\n+ishsZDM8eNNdp3Ew+fEYVvY1W7mR1qU24NWj0bzVsClI7hvPVIuw7AjfBDq1C5+\r\nA+ZSLSXYvOK2cEWjdxQfuNZwEZSjmA63DUllBIrm35IaTvfuyhU6BW9yHZxmb8+M\r\nw0xDv30D5UkE\/2N7Pa\/HQJLxCR+3zKibRK3nUyRDLSXxMkU9PnFNaPNX59VPgyj4\r\nGB1CFSToldJVPF4pzh7p36uGXZVxs8m3LFD4Ol8mhi7jkxDZjqFN46gzR0r23Py6\r\ndol9vfawGIoUwp9LvL0S7MvdRY0oazLXwClLP4OQ17zpSMAiCj7fgNT661JamPGj\r\nt5O7Zn2wA7I4ddDS\/HDTWCu98Zwc9fHIpsJPgCZ9awoqxi4Mnf7Pk9g5nnXhszGC\r\ncxxIASQKM+GhdzoRxKknax2RzUCwCzcPRtCj8AQT\/x\/mqN3PfRmlnFBNACUw9bpZ\r\nSOoNq2pCF9igftDWpSIXQ38pVpKLWowjjg3DVRmVKBgivHnUnVLyzYBahHPj0vaz\r\ntFtUFRaqXDnt+4qyUGyrT5h5pjZaTcHIcSB4PiarYwdVvgslgwnQzOUcGAzRWBD4\r\n6jV2brP5vFY3g6iPAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBACTY3CCHC+Z28gCf\r\nFWGKQ3wAKs+k4+0yoti0qm2EKX7rSGQ0PHSas6uW79WstC4Rj+DYkDtIhGMSg8FS\r\nHVGZHGBCc0HwdX+BOAt3zi4p7Sf3oQef70\/4imPoKxbAVCpd\/cveVcFyDC19j1yB\r\nBapwu87oh+muoeaZxOlqQI4UxjBlR\/uRSMhOn2UGauIr3dWJgAF4pGt7TtIzt+1v\r\n0uA6FtN1Y4R5O8AaJPh1bIG0CVvFBE58esGzjEYLhOydgKFnEP94kVPgJD5ds9C3\r\npPhEpo1dRpiXaF7WGIV1X6DI\/ipWvfrF7CEy6I\/kP1InY\/vMDjQjeDnJ\/VrXIWXO\r\nyZvHXVaN\/m+1RlETsH7YO\/QmxRue9ZHN3gvvWtmpCeA95sfpepOk7UcHxHZYyQbF\r\n49\/au8j+5tsr4A83xzsT1JbcKRxkAaQ7WDJpOnE5O1+H0fB+BaLakTg6XX9d4Fo7\r\n7Gin7hVWX7pL+JIyxMzME3LhfI61+CRcqZQIrpyaafUziPQbWIPfEs7h8tCOWyvW\r\nUO8ZLervYCB3j44ivkrxPlcBklDCqqKKBzDP9dYOtS\/P4RB1NkHA9+NTvmBpTonS\r\nSFXdg9fFMD7VfjDE3Vnk+8DWkVH5wBYowTAD7w9Wuzr7DumiAULexnP\/Y7xwxLv7\r\n4B+pXTAcRK0zECDEaX3npS8xWzrB\r\n-----END CERTIFICATE-----"
  120. }';
  121. $this->fileAccessHelper
  122. ->expects($this->once())
  123. ->method('file_put_contents')
  124. ->with(
  125. $this->equalTo(\OC::$SERVERROOT . '/tests/data/integritycheck/app//appinfo/signature.json'),
  126. $this->callback(function ($signature) use ($expectedSignatureFileData) {
  127. $expectedArray = json_decode($expectedSignatureFileData, true);
  128. $actualArray = json_decode($signature, true);
  129. $this->assertEquals($expectedArray, $actualArray);
  130. return true;
  131. })
  132. );
  133. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
  134. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
  135. $rsa = new RSA();
  136. $rsa->loadKey($rsaPrivateKey);
  137. $x509 = new X509();
  138. $x509->loadX509($keyBundle);
  139. $this->checker->writeAppSignature(\OC::$SERVERROOT . '/tests/data/integritycheck/app/', $x509, $rsa);
  140. }
  141. public function testVerifyAppSignatureWithoutSignatureData() {
  142. $this->environmentHelper
  143. ->expects($this->once())
  144. ->method('getChannel')
  145. ->willReturn('stable');
  146. $this->config
  147. ->expects($this->any())
  148. ->method('getSystemValue')
  149. ->with('integrity.check.disabled', false)
  150. ->willReturn(false);
  151. $expected = [
  152. 'EXCEPTION' => [
  153. 'class' => 'OC\IntegrityCheck\Exceptions\InvalidSignatureException',
  154. 'message' => 'Signature data not found.',
  155. ],
  156. ];
  157. $this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp'));
  158. }
  159. public function testVerifyAppSignatureWithValidSignatureData() {
  160. $this->environmentHelper
  161. ->expects($this->once())
  162. ->method('getChannel')
  163. ->willReturn('stable');
  164. $this->config
  165. ->expects($this->any())
  166. ->method('getSystemValue')
  167. ->with('integrity.check.disabled', false)
  168. ->willReturn(false);
  169. $this->appLocator
  170. ->expects($this->once())
  171. ->method('getAppPath')
  172. ->with('SomeApp')
  173. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  174. $signatureDataFile = '{
  175. "hashes": {
  176. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  177. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  178. },
  179. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  180. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  181. }';
  182. $this->fileAccessHelper
  183. ->expects($this->at(0))
  184. ->method('file_get_contents')
  185. ->with(
  186. \OC::$SERVERROOT . '/tests/data/integritycheck/app//appinfo/signature.json'
  187. )
  188. ->willReturn($signatureDataFile);
  189. $this->fileAccessHelper
  190. ->expects($this->at(1))
  191. ->method('file_get_contents')
  192. ->with(
  193. '/resources/codesigning/root.crt'
  194. )
  195. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  196. $this->assertSame([], $this->checker->verifyAppSignature('SomeApp'));
  197. }
  198. public function testVerifyAppSignatureWithTamperedSignatureData() {
  199. $this->environmentHelper
  200. ->expects($this->once())
  201. ->method('getChannel')
  202. ->willReturn('stable');
  203. $this->config
  204. ->expects($this->any())
  205. ->method('getSystemValue')
  206. ->with('integrity.check.disabled', false)
  207. ->willReturn(false);
  208. $this->appLocator
  209. ->expects($this->once())
  210. ->method('getAppPath')
  211. ->with('SomeApp')
  212. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  213. $signatureDataFile = '{
  214. "hashes": {
  215. "AnotherFile.txt": "tampered",
  216. "subfolder\/file.txt": "tampered"
  217. },
  218. "signature": "EL49UaSeyMAqyMtqId+tgOhhwgOevPZsRLX4j2blnybAB6fN07z0936JqZV7+eMPiE30Idx+UCY6rCFN531Kqe9vAOCdgtHUSOjjKyKc+lvULESlMb6YQcrZrvDlEMMjzjH49ewG7Ai8sNN6HrRUd9U8ws+ewSkW2DOOBItj\/21RBnkrSt+2AtGXGigEvuTm57HrCYDj8\/lSkumC2GVkjLUHeLOKYo4PRNOr6yP5mED5v7zo66AWvXl2fKv54InZcdxsAk35lyK9DGZbk\/027ZRd0AOHT3LImRLvQ+8EAg3XLlRUy0hOFGgPC+jYonMzgYvsAXAXi2j8LnLJlsLwpFwu1k1B+kZVPMumKZvP9OvJb70EirecXmz62V+Jiyuaq7ne4y7Kp5gKZT\/T8SeZ0lFtCmPfYyzBB0y8s5ldmTTmdVYHs54t\/OCCW82HzQZxnFNPzDTRa8HglsaMKrqPtW59+R4UvRKSWhB8M\/Ah57qgzycvPV4KMz\/FbD4l\/\/9chRKSlCfc2k3b8ZSHNmi+EzCKgJjWIoKdgN1yax94puU8jfn8UW+G7H9Y1Jsf\/jox6QLyYEgtV1vOHY2xLT7fVs2vhyvkN2MNjJnmQ70gFG5Qz2lBz5wi6ZpB+tOfCcpbLxWAkoWoIrmC\/Ilqh7mfmRZ43g5upjkepHNd93ONuY8=",
  219. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEwTCCAqmgAwIBAgIUWv0iujufs5lUr0svCf\/qTQvoyKAwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIyNDk1M1oXDTE2MTEwMzIyNDk1M1owEjEQMA4GA1UEAwwHU29tZUFwcDCCAiIw\r\nDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK8q0x62agGSRBqeWsaeEwFfepMk\r\nF8cAobMMi50qHCv9IrOn\/ZH9l52xBrbIkErVmRjmly0d4JhD8Ymhidsh9ONKYl\/j\r\n+ishsZDM8eNNdp3Ew+fEYVvY1W7mR1qU24NWj0bzVsClI7hvPVIuw7AjfBDq1C5+\r\nA+ZSLSXYvOK2cEWjdxQfuNZwEZSjmA63DUllBIrm35IaTvfuyhU6BW9yHZxmb8+M\r\nw0xDv30D5UkE\/2N7Pa\/HQJLxCR+3zKibRK3nUyRDLSXxMkU9PnFNaPNX59VPgyj4\r\nGB1CFSToldJVPF4pzh7p36uGXZVxs8m3LFD4Ol8mhi7jkxDZjqFN46gzR0r23Py6\r\ndol9vfawGIoUwp9LvL0S7MvdRY0oazLXwClLP4OQ17zpSMAiCj7fgNT661JamPGj\r\nt5O7Zn2wA7I4ddDS\/HDTWCu98Zwc9fHIpsJPgCZ9awoqxi4Mnf7Pk9g5nnXhszGC\r\ncxxIASQKM+GhdzoRxKknax2RzUCwCzcPRtCj8AQT\/x\/mqN3PfRmlnFBNACUw9bpZ\r\nSOoNq2pCF9igftDWpSIXQ38pVpKLWowjjg3DVRmVKBgivHnUnVLyzYBahHPj0vaz\r\ntFtUFRaqXDnt+4qyUGyrT5h5pjZaTcHIcSB4PiarYwdVvgslgwnQzOUcGAzRWBD4\r\n6jV2brP5vFY3g6iPAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBACTY3CCHC+Z28gCf\r\nFWGKQ3wAKs+k4+0yoti0qm2EKX7rSGQ0PHSas6uW79WstC4Rj+DYkDtIhGMSg8FS\r\nHVGZHGBCc0HwdX+BOAt3zi4p7Sf3oQef70\/4imPoKxbAVCpd\/cveVcFyDC19j1yB\r\nBapwu87oh+muoeaZxOlqQI4UxjBlR\/uRSMhOn2UGauIr3dWJgAF4pGt7TtIzt+1v\r\n0uA6FtN1Y4R5O8AaJPh1bIG0CVvFBE58esGzjEYLhOydgKFnEP94kVPgJD5ds9C3\r\npPhEpo1dRpiXaF7WGIV1X6DI\/ipWvfrF7CEy6I\/kP1InY\/vMDjQjeDnJ\/VrXIWXO\r\nyZvHXVaN\/m+1RlETsH7YO\/QmxRue9ZHN3gvvWtmpCeA95sfpepOk7UcHxHZYyQbF\r\n49\/au8j+5tsr4A83xzsT1JbcKRxkAaQ7WDJpOnE5O1+H0fB+BaLakTg6XX9d4Fo7\r\n7Gin7hVWX7pL+JIyxMzME3LhfI61+CRcqZQIrpyaafUziPQbWIPfEs7h8tCOWyvW\r\nUO8ZLervYCB3j44ivkrxPlcBklDCqqKKBzDP9dYOtS\/P4RB1NkHA9+NTvmBpTonS\r\nSFXdg9fFMD7VfjDE3Vnk+8DWkVH5wBYowTAD7w9Wuzr7DumiAULexnP\/Y7xwxLv7\r\n4B+pXTAcRK0zECDEaX3npS8xWzrB\r\n-----END CERTIFICATE-----"
  220. }';
  221. $this->fileAccessHelper
  222. ->expects($this->at(0))
  223. ->method('file_get_contents')
  224. ->with(
  225. \OC::$SERVERROOT . '/tests/data/integritycheck/app//appinfo/signature.json'
  226. )
  227. ->willReturn($signatureDataFile);
  228. $this->fileAccessHelper
  229. ->expects($this->at(1))
  230. ->method('file_get_contents')
  231. ->with(
  232. '/resources/codesigning/root.crt'
  233. )
  234. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  235. $expected = [
  236. 'EXCEPTION' => [
  237. 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
  238. 'message' => 'Signature could not get verified.',
  239. ],
  240. ];
  241. $this->assertEquals($expected, $this->checker->verifyAppSignature('SomeApp'));
  242. }
  243. public function testVerifyAppSignatureWithTamperedFiles() {
  244. $this->environmentHelper
  245. ->expects($this->once())
  246. ->method('getChannel')
  247. ->willReturn('stable');
  248. $this->config
  249. ->expects($this->any())
  250. ->method('getSystemValue')
  251. ->with('integrity.check.disabled', false)
  252. ->willReturn(false);
  253. $this->appLocator
  254. ->expects($this->once())
  255. ->method('getAppPath')
  256. ->with('SomeApp')
  257. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/');
  258. $signatureDataFile = '{
  259. "hashes": {
  260. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  261. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  262. },
  263. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  264. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  265. }';
  266. $this->fileAccessHelper
  267. ->expects($this->at(0))
  268. ->method('file_get_contents')
  269. ->with(
  270. \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//appinfo/signature.json'
  271. )
  272. ->willReturn($signatureDataFile);
  273. $this->fileAccessHelper
  274. ->expects($this->at(1))
  275. ->method('file_get_contents')
  276. ->with(
  277. '/resources/codesigning/root.crt'
  278. )
  279. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  280. $expected = [
  281. 'INVALID_HASH' => [
  282. 'AnotherFile.txt' => [
  283. 'expected' => '1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112',
  284. 'current' => '7322348ba269c6d5522efe02f424fa3a0da319a7cd9c33142a5afe32a2d9af2da3a411f086fcfc96ff4301ea566f481dba0960c2abeef3594c4d930462f6584c',
  285. ],
  286. ],
  287. 'FILE_MISSING' => [
  288. 'subfolder/file.txt' => [
  289. 'expected' => '410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b',
  290. 'current' => '',
  291. ],
  292. ],
  293. 'EXTRA_FILE' => [
  294. 'UnecessaryFile' => [
  295. 'expected' => '',
  296. 'current' => 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
  297. ],
  298. ],
  299. ];
  300. $this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp'));
  301. }
  302. public function testVerifyAppSignatureWithTamperedFilesAndAlternatePath() {
  303. $this->environmentHelper
  304. ->expects($this->once())
  305. ->method('getChannel')
  306. ->willReturn('stable');
  307. $this->config
  308. ->expects($this->any())
  309. ->method('getSystemValue')
  310. ->with('integrity.check.disabled', false)
  311. ->willReturn(false);
  312. $this->appLocator
  313. ->expects($this->never())
  314. ->method('getAppPath')
  315. ->with('SomeApp');
  316. $signatureDataFile = '{
  317. "hashes": {
  318. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  319. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  320. },
  321. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  322. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  323. }';
  324. $this->fileAccessHelper
  325. ->expects($this->at(0))
  326. ->method('file_get_contents')
  327. ->with(
  328. \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//appinfo/signature.json'
  329. )
  330. ->willReturn($signatureDataFile);
  331. $this->fileAccessHelper
  332. ->expects($this->at(1))
  333. ->method('file_get_contents')
  334. ->with(
  335. '/resources/codesigning/root.crt'
  336. )
  337. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  338. $expected = [
  339. 'INVALID_HASH' => [
  340. 'AnotherFile.txt' => [
  341. 'expected' => '1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112',
  342. 'current' => '7322348ba269c6d5522efe02f424fa3a0da319a7cd9c33142a5afe32a2d9af2da3a411f086fcfc96ff4301ea566f481dba0960c2abeef3594c4d930462f6584c',
  343. ],
  344. ],
  345. 'FILE_MISSING' => [
  346. 'subfolder/file.txt' => [
  347. 'expected' => '410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b',
  348. 'current' => '',
  349. ],
  350. ],
  351. 'EXTRA_FILE' => [
  352. 'UnecessaryFile' => [
  353. 'expected' => '',
  354. 'current' => 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
  355. ],
  356. ],
  357. ];
  358. $this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp', \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/'));
  359. }
  360. public function testVerifyAppWithDifferentScope() {
  361. $this->environmentHelper
  362. ->expects($this->once())
  363. ->method('getChannel')
  364. ->willReturn('stable');
  365. $this->config
  366. ->expects($this->any())
  367. ->method('getSystemValue')
  368. ->with('integrity.check.disabled', false)
  369. ->willReturn(false);
  370. $this->appLocator
  371. ->expects($this->once())
  372. ->method('getAppPath')
  373. ->with('SomeApp')
  374. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/');
  375. $signatureDataFile = '{
  376. "hashes": {
  377. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  378. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  379. },
  380. "signature": "eXesvDm3pkek12xSwMG10y9suRES79Nye3jYNe5KYq1tTUPqRRNgxmMGAfcUro0zpLeAr2YgHeSMWtglblGOW7pmwGVPZ0O1Y4r1fE6jnep0kW+35PLIaqCorIOnCAtSzDNKBhwd1ow3zW2wC0DFouuEkIO8u5Fw28g8E8dp8zEk1xMblNPy+xtWkmYHrVJ\/dQgun1bYOF2ZFtAzatwndTI\/bGsy1i3Wsl+x6HyWKQdq8y8VObtOqKDH7uERBEpB9DHVyKflj1v1gQuEH6BhaRdATc7ee0MiQdGblraIySwYRdfo2d8i82OVKrenMB3SLwyCvDPyQ9iKpTOnSF52ZBqaqSXKM2N\/RAkweeBFQQCwcHhqxvB0cfbyHcbkOLeCZe\/tsh68IxwTiYgzvLfl7sOZ5arnZbzrPpZmB+hfV2omkoJ1tDwOWz9hEmLLNtfo2OxyUH1m0+XFaC+Gbn4WkVDgf7YZkwUcG+Qoa3oKDNMss8MEyZxewl2iDGZcf402dlidHRprlfmXbAYuVQ08\/a0HxIKYPGh\/nsMGmwnO15CWtFpAbhUA\/D5oRjsIxnvXaMDg0iAFpdu\/5Ffsj7g3EPdBkiQHNYK7YU1RRx609eH0bZyiIYHdUPw7ikLupvrebZmELqi3mqDFO99u4eISlxFJlUbUND3L4BtmWTWrKwI=",
  381. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIExjCCAq6gAwIBAgIUHSJjhJqMwr+3TkoiQFg4SVVYQ1gwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIzMjc1NVoXDTE2MTEwMzIzMjc1NVowFzEVMBMGA1UEAwwMQW5vdGhlclNjb3Bl\r\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA33npb5RmUkXrDT+TbwMf\r\n0zQ33SlzsjoGxCrbSwJOn6leGGInJ6ZrdzLL0WTi\/dTpg+Y\/JS+72XWm5NSjaTxo\r\n7OHc3cQBwXQj4tN6j\/y5qqY0GDLYufEkx2rpazqt9lBSJ72u1bGl2yoOXzYCz5i0\r\n60KsJXC9K44LKzGsarzbwAgskSVNkjAsPgjnCWZmcl6icpLi5Fz9rs2UMOWbdvdI\r\nAROsn0eC9E\/akmXTy5YMu6bAIGpvjZFHzyA83FQRbvv5o1V5Gsye\/VQLEgh7rqfz\r\nT\/jgWifP+JgoeB6otzuRZ3fFsmbBiyCIRtIOzQQflozhUlWtmiEGwg4GySuMUjEH\r\nA1LF86LO+ZzDQgd2oYNKmrQ8O+EcLqx9BpV4AFhEvqdk7uycJYPHs6yl+yfbzTeJ\r\n2Xd0yVAfd9r\/iDr36clLj2bzEObdl9xzKjcCIXE4Q0G4Pur41\/BJUDK9PI390ccQ\r\nnFjjVYBMsC859OwW64tMP0zkM9Vv72LCaEzaR8jqH0j11catqxunr+StfMcmxLTN\r\nbqBJbSEq4ER3mJxCTI2UrIVmdQ7+wRxgv3QTDNOZyqrz2L8A1Rpb3h0APxtQv+oA\r\n8KIZYID5\/qsS2V2jITkMQ8Nd1W3b0cZhZ600z+znh3jLJ0TYLvwN6\/qBQTUDaM2o\r\ng1+icMqXIXIeKuoPCVVsG7cCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAHc4F\/kOV\r\nHc8In5MmGg2YtjwZzjdeoC5TIPZczRqz0B+wRbJzN6aYryKZKLmP+wKpgRnJWDzp\r\nrgKGyyEQIAfK63DEv4B9p4N1B+B3aeMKsSpVcw7wbFTD57V5A7pURGoo31d0mw5L\r\nUIXZ2u+TUfGbzucMxLdFhTwjGpz9M6Kkm\/POxmV0tvLija5LdbdKnYR9BFmyu4IX\r\nqyoIAtComATNLl+3URu3SZxhE3NxhzMz+eAeNfh1KuIf2gWIIeDCXalVSJLym+OQ\r\nHFDpqRhJqfTMprrRlmmU7Zntgbj8\/RRZuXnBvH9cQ2KykLOb4UoCPlGUqOqKyP9m\r\nDJSFRiMJfpgMQUaJk1TLhKF+IR6FnmwURLEtkONJumtDQju9KaWPlhueONdyGi0p\r\nqxLVUo1Vb52XnPhk2GEEduxpDc9V5ePJ+pdcEdMifY\/uPNBRuBj2c87yq1DLH+U4\r\n3XzP1MlwjnBWZYuoFo0j6Jq0r\/MG6HjGdmkGIsRoheRi8Z8Scz5AW5QRkNz8pKop\r\nTELFqQy9g6TyQzzC8t6HZcpNe842ZUk4raEAbCZe\/XqxWMw5svPgNceBqM3fh7sZ\r\nBSykOHLaL8kiRO\/IS3y1yZEAuiWBvtxcTNLzBb+hdRpm2y8\/qH\/pKo+CMj1VzjNT\r\nD8YRQg0cjmDytJzHDrtV\/aTc9W1aPHun0vw=\r\n-----END CERTIFICATE-----"
  382. }';
  383. $this->fileAccessHelper
  384. ->expects($this->at(0))
  385. ->method('file_get_contents')
  386. ->with(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//appinfo/signature.json')
  387. ->willReturn($signatureDataFile);
  388. $this->fileAccessHelper
  389. ->expects($this->at(1))
  390. ->method('file_get_contents')
  391. ->with(
  392. '/resources/codesigning/root.crt'
  393. )
  394. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  395. $expected = [
  396. 'EXCEPTION' => [
  397. 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
  398. 'message' => 'Certificate is not valid for required scope. (Requested: SomeApp, current: CN=AnotherScope)',
  399. ],
  400. ];
  401. $this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp'));
  402. }
  403. public function testVerifyAppWithDifferentScopeAndAlwaysTrustedCore() {
  404. $this->environmentHelper
  405. ->expects($this->once())
  406. ->method('getChannel')
  407. ->willReturn('stable');
  408. $this->config
  409. ->expects($this->any())
  410. ->method('getSystemValue')
  411. ->with('integrity.check.disabled', false)
  412. ->willReturn(false);
  413. $this->appLocator
  414. ->expects($this->once())
  415. ->method('getAppPath')
  416. ->with('SomeApp')
  417. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  418. $signatureDataFile = '{
  419. "hashes": {
  420. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  421. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  422. },
  423. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  424. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  425. }';
  426. $this->fileAccessHelper
  427. ->expects($this->at(0))
  428. ->method('file_get_contents')
  429. ->with(\OC::$SERVERROOT . '/tests/data/integritycheck/app//appinfo/signature.json')
  430. ->willReturn($signatureDataFile);
  431. $this->fileAccessHelper
  432. ->expects($this->at(1))
  433. ->method('file_get_contents')
  434. ->with(
  435. '/resources/codesigning/root.crt'
  436. )
  437. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  438. $this->assertSame([], $this->checker->verifyAppSignature('SomeApp'));
  439. }
  440. public function testWriteCoreSignatureWithException() {
  441. $this->expectException(\Exception::class);
  442. $this->expectExceptionMessage('Exception message');
  443. $this->fileAccessHelper
  444. ->expects($this->at(0))
  445. ->method('assertDirectoryExists')
  446. ->will($this->throwException(new \Exception('Exception message')));
  447. $this->fileAccessHelper
  448. ->expects($this->at(1))
  449. ->method('is_writable')
  450. ->with(__DIR__ . '/core')
  451. ->willReturn(true);
  452. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
  453. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
  454. $rsa = new RSA();
  455. $rsa->loadKey($rsaPrivateKey);
  456. $x509 = new X509();
  457. $x509->loadX509($keyBundle);
  458. $this->checker->writeCoreSignature($x509, $rsa, __DIR__);
  459. }
  460. public function testWriteCoreSignatureWrongPermissions() {
  461. $this->expectException(\Exception::class);
  462. $this->expectExceptionMessageMatches('/[a-zA-Z\\/_-]+ is not writable/');
  463. $this->fileAccessHelper
  464. ->expects($this->at(0))
  465. ->method('assertDirectoryExists')
  466. ->will($this->throwException(new \Exception('Exception message')));
  467. $this->fileAccessHelper
  468. ->expects($this->at(1))
  469. ->method('is_writable')
  470. ->with(__DIR__ . '/core')
  471. ->willReturn(false);
  472. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
  473. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
  474. $rsa = new RSA();
  475. $rsa->loadKey($rsaPrivateKey);
  476. $x509 = new X509();
  477. $x509->loadX509($keyBundle);
  478. $this->checker->writeCoreSignature($x509, $rsa, __DIR__);
  479. }
  480. public function testWriteCoreSignature() {
  481. $expectedSignatureFileData = '{
  482. "hashes": {
  483. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  484. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  485. },
  486. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  487. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  488. }';
  489. $this->environmentHelper
  490. ->expects($this->any())
  491. ->method('getServerRoot')
  492. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  493. $this->fileAccessHelper
  494. ->expects($this->once())
  495. ->method('file_put_contents')
  496. ->with(
  497. \OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json',
  498. $this->callback(function ($signature) use ($expectedSignatureFileData) {
  499. $expectedArray = json_decode($expectedSignatureFileData, true);
  500. $actualArray = json_decode($signature, true);
  501. $this->assertEquals($expectedArray, $actualArray);
  502. return true;
  503. })
  504. );
  505. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/core.crt');
  506. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/core.key');
  507. $rsa = new RSA();
  508. $rsa->loadKey($rsaPrivateKey);
  509. $x509 = new X509();
  510. $x509->loadX509($keyBundle);
  511. $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  512. }
  513. public function testWriteCoreSignatureWithUnmodifiedHtaccess() {
  514. $expectedSignatureFileData = '{
  515. "hashes": {
  516. ".htaccess": "dc479770a6232061e04a768ee1f9133fdb3aea7b3a99f7105b0e0b6197474733e8d14b5b2bbad054e6b62a410fe5d0b3d790242dee1e0f11274af2100f5289e2",
  517. "subfolder\/.htaccess": "2c57b1e25050e11dc3ae975832f378c452159f7b69f818e47eeeafadd6ba568517461dcb4d843b90b906cd7c89d161bc1b89dff8e3ae0eb6f5088508c47befd1"
  518. },
  519. "signature": "nRtR377DB\/I\/4hmh9q3elMQYfSHnQFlNtjchNgrdfmUQqVmgkU\/4qgGyxDqYkV8mSMbH2gYysfP42nx\/3zSo7n0dBYDfU87Q6f96Cv597vEV27do8CaBkEk8Xjn2SxhHw8hVxracvE2OBAPxk0H3sRp\/cQBgjoXpju4kQin0N5E+DEJMh7Sp+u8aKoFpb+2FaAZJFn\/hnqxLTlVi2nyDxGL3U0eobWY+jWH9XPt52v3Hyh8TDhcAnQ1cN30B8Jn2+jkrm8ib+buchaCXHk0cPX72xuPECdwOEKLCBNrJa3FGSvO1zWiecnCgxCXgt+R8hUgsVPTsbrdFY2YRJGIhHndYZL98XzgG7cw85SnnMMe2SulzeL7xANGF8qiEVyiC7x83bbj5xOkeM\/CUTajrLBO3vyZ23KKOxvskjgI0t+Zw1zFsl+sYW0\/O\/V5WzPOwMwV8+iApQ8k9gEMiYQg98QLEMYnSohncmp0Z9qx2qFcQuHLcKJVa1J6wGtE\/EHR\/4d0aYPd6IRjg+qshCJmdzud\/12xjpGTl+BT0Hi0VsU5o7ZMi7WhmukZmmv8u0uZsvKREQNATm4cO4WCkYySt5O9gZEJOF+jjgeynDoAh09lyrNXIgMpM9ufm\/XEG\/I\/f2zIwbAUc6J6qks5OuYlJzW5vscTiOKhwcGZU9WBLgh0=",
  520. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  521. }';
  522. $this->environmentHelper
  523. ->expects($this->any())
  524. ->method('getServerRoot')
  525. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/htaccessUnmodified/');
  526. $this->fileAccessHelper
  527. ->expects($this->once())
  528. ->method('file_put_contents')
  529. ->with(
  530. \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessUnmodified//core/signature.json',
  531. $this->callback(function ($signature) use ($expectedSignatureFileData) {
  532. $expectedArray = json_decode($expectedSignatureFileData, true);
  533. $actualArray = json_decode($signature, true);
  534. $this->assertEquals($expectedArray, $actualArray);
  535. return true;
  536. })
  537. );
  538. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/core.crt');
  539. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/core.key');
  540. $rsa = new RSA();
  541. $rsa->loadKey($rsaPrivateKey);
  542. $x509 = new X509();
  543. $x509->loadX509($keyBundle);
  544. $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessUnmodified/');
  545. }
  546. public function testWriteCoreSignatureWithInvalidModifiedHtaccess() {
  547. $expectedSignatureFileData = '{
  548. "hashes": {
  549. ".htaccess": "4a54273dc8d697b2ca615acf2ae2c1ee3c1c643492cb04f42b10984fa9aacff1420dc829fd82f93ad3476fbd0cdab0251142c887dc8f872d03e39a3a3eb6d381"
  550. },
  551. "signature": "qpDddYGgAKNR3TszOgjPXRphUl2P9Ym5OQaetltocgZASGDkOun5D64+1D0QJRKb4SG2+48muxGOHyL2Ngos4NUrrSR+SIkywZacay82YQBCEdr7\/4MjW1WHRPjvboLwEJwViw0EdAjsWRpD68aPnzUGrGsy2BsCo06P5iwjk9cXcHxdjC9R39npvoC3QNvQ2jmNIbh1Lc4U97dbb+CsXEQCLU1OSa9p3q6cEFV98Easwt7uF\/DzHK+CbeZlxVZ0DwLh2\/ylT1PyGou8QC1b3vKAnPjLWMO+UsCPpCKhk3C5pV+5etQ8puGd+0x2t5tEU+qXxLzek91zWNC+rqgC\/WlqLKbwPb\/BCHs4zLGV55Q2fEQmT21x0KCUELdPs4dBnYP4Ox5tEDugtJujWFzOHzoY6gGa\/BY\/78pSZXmq9o8dWkBEtioWWvaNZ1rM0ddE83GBlBTgjigi9Ay1D++bUW\/FCBB7CMk6qyNlV81H+cBuIEODw2aymmkM9LLDD2Qbmvo8gHEPRjiQxPC5OpDlcdSNiL+zcxVxeuX4FpT+9xzz\/\/DRONhufxRpsbuCOMxd96RW7y9U2N2Uxb3Bzn\/BIqEayUUsdgZjfaGcXXYKR+chu\/LOwNYN6RlnLsgqL\/dhGKwlRVKXw1RA2\/af\/CpqyR7uVP6al1YJo\/YJ+5XJ6zE=",
  552. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  553. }';
  554. $this->fileAccessHelper
  555. ->expects($this->once())
  556. ->method('file_put_contents')
  557. ->with(
  558. \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithInvalidModifiedContent//core/signature.json',
  559. $this->callback(function ($signature) use ($expectedSignatureFileData) {
  560. $expectedArray = json_decode($expectedSignatureFileData, true);
  561. $actualArray = json_decode($signature, true);
  562. $this->assertEquals($expectedArray, $actualArray);
  563. return true;
  564. })
  565. );
  566. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/core.crt');
  567. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/core.key');
  568. $rsa = new RSA();
  569. $rsa->loadKey($rsaPrivateKey);
  570. $x509 = new X509();
  571. $x509->loadX509($keyBundle);
  572. $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithInvalidModifiedContent/');
  573. }
  574. public function testWriteCoreSignatureWithValidModifiedHtaccess() {
  575. $expectedSignatureFileData = '{
  576. "hashes": {
  577. ".htaccess": "7e6a7a4d8ee4f3fbc45dd579407c643471575a9d127d1c75f6d0a49e80766c3c587104b2139ef76d2a4bffce3f45777900605aaa49519c9532909b71e5030227",
  578. "subfolder\/.htaccess": "2c57b1e25050e11dc3ae975832f378c452159f7b69f818e47eeeafadd6ba568517461dcb4d843b90b906cd7c89d161bc1b89dff8e3ae0eb6f5088508c47befd1"
  579. },
  580. "signature": "YVwQvl9Dh8UebCumfgzFxfz3NiZJLmYG8oJVTfEBhulI4KXBnTG1jZTprf4XxG2XIriEYAZXsoXpu9xWsUFe9QfdncwoEpqJtGq7l6aVDTofX5Be5b03MQFJr4cflgllqW77QZ84D9O9qWF\/vNDAofXcwrzT04CxLDhyQgTCgYUnRjG9pnuP\/gtbDKbTjRvxhTyfg3T0Phv1+XAvpTPnH2q5A+1+LmiqziUJ1sMipsKo+jQP614eCi9qjmqhHIgLRgcuOBvsi4g5WUcdcAIZ6qLt5gm2Y3r6rKNVchosU9ZydMUTfjuejDbVwE2fNH5UUnV57fQBxwg9CfX7iFHqKv1bfv5Zviu12paShgWCB12uR3iH\/3lmTJn8K5Xqit3G4eymFaJ5IChdUThBp\/jhQSI2r8sPcZDYSJ\/UZKuFnezFdKhEBd5hMXe8aKAd6ijGDjLARksFuqpi1sS8llC5K1Q+DzktSL\/o64TY4Vuvykiwe\/BAk2SkL9voOtrvU7vfDBcuCPbDJnSBBC0ESpcXeClTBIn6xZ9WaxqoS7sinE\/kUwtWsRd04I7d79\/ouotyNb+mBhTuRsZT12p\/gn4JHXXNUAIpTwchYzGxbfNJ4kxnYBFZWVmvsSqOLFZu1yi5BP3ktA9yhFyWIa5659azRFEKRdXpVHtQVa4IgdhxEqA=",
  581. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  582. }';
  583. $this->environmentHelper
  584. ->expects($this->any())
  585. ->method('getServerRoot')
  586. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent');
  587. $this->fileAccessHelper
  588. ->expects($this->once())
  589. ->method('file_put_contents')
  590. ->with(
  591. \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent/core/signature.json',
  592. $this->callback(function ($signature) use ($expectedSignatureFileData) {
  593. $expectedArray = json_decode($expectedSignatureFileData, true);
  594. $actualArray = json_decode($signature, true);
  595. $this->assertEquals($expectedArray, $actualArray);
  596. return true;
  597. })
  598. );
  599. $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/core.crt');
  600. $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/core.key');
  601. $rsa = new RSA();
  602. $rsa->loadKey($rsaPrivateKey);
  603. $x509 = new X509();
  604. $x509->loadX509($keyBundle);
  605. $this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent');
  606. }
  607. public function testVerifyCoreSignatureWithoutSignatureData() {
  608. $this->environmentHelper
  609. ->expects($this->once())
  610. ->method('getChannel')
  611. ->willReturn('stable');
  612. $this->config
  613. ->expects($this->any())
  614. ->method('getSystemValue')
  615. ->with('integrity.check.disabled', false)
  616. ->willReturn(false);
  617. $expected = [
  618. 'EXCEPTION' => [
  619. 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
  620. 'message' => 'Signature data not found.',
  621. ],
  622. ];
  623. $this->assertSame($expected, $this->checker->verifyCoreSignature());
  624. }
  625. public function testVerifyCoreSignatureWithValidSignatureData() {
  626. $this->environmentHelper
  627. ->expects($this->once())
  628. ->method('getChannel')
  629. ->willReturn('stable');
  630. $this->config
  631. ->expects($this->any())
  632. ->method('getSystemValue')
  633. ->with('integrity.check.disabled', false)
  634. ->willReturn(false);
  635. $this->environmentHelper
  636. ->expects($this->any())
  637. ->method('getServerRoot')
  638. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  639. $signatureDataFile = '{
  640. "hashes": {
  641. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  642. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  643. },
  644. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  645. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  646. }';
  647. $this->fileAccessHelper
  648. ->expects($this->at(0))
  649. ->method('file_get_contents')
  650. ->with(
  651. \OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json'
  652. )
  653. ->willReturn($signatureDataFile);
  654. $this->fileAccessHelper
  655. ->expects($this->at(1))
  656. ->method('file_get_contents')
  657. ->with(
  658. \OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
  659. )
  660. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  661. $this->assertSame([], $this->checker->verifyCoreSignature());
  662. }
  663. public function testVerifyCoreSignatureWithValidModifiedHtaccessSignatureData() {
  664. $this->environmentHelper
  665. ->expects($this->once())
  666. ->method('getChannel')
  667. ->willReturn('stable');
  668. $this->config
  669. ->expects($this->any())
  670. ->method('getSystemValue')
  671. ->with('integrity.check.disabled', false)
  672. ->willReturn(false);
  673. $this->environmentHelper
  674. ->expects($this->any())
  675. ->method('getServerRoot')
  676. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent');
  677. $signatureDataFile = '{
  678. "hashes": {
  679. ".htaccess": "7e6a7a4d8ee4f3fbc45dd579407c643471575a9d127d1c75f6d0a49e80766c3c587104b2139ef76d2a4bffce3f45777900605aaa49519c9532909b71e5030227",
  680. "subfolder\/.htaccess": "2c57b1e25050e11dc3ae975832f378c452159f7b69f818e47eeeafadd6ba568517461dcb4d843b90b906cd7c89d161bc1b89dff8e3ae0eb6f5088508c47befd1"
  681. },
  682. "signature": "YVwQvl9Dh8UebCumfgzFxfz3NiZJLmYG8oJVTfEBhulI4KXBnTG1jZTprf4XxG2XIriEYAZXsoXpu9xWsUFe9QfdncwoEpqJtGq7l6aVDTofX5Be5b03MQFJr4cflgllqW77QZ84D9O9qWF\/vNDAofXcwrzT04CxLDhyQgTCgYUnRjG9pnuP\/gtbDKbTjRvxhTyfg3T0Phv1+XAvpTPnH2q5A+1+LmiqziUJ1sMipsKo+jQP614eCi9qjmqhHIgLRgcuOBvsi4g5WUcdcAIZ6qLt5gm2Y3r6rKNVchosU9ZydMUTfjuejDbVwE2fNH5UUnV57fQBxwg9CfX7iFHqKv1bfv5Zviu12paShgWCB12uR3iH\/3lmTJn8K5Xqit3G4eymFaJ5IChdUThBp\/jhQSI2r8sPcZDYSJ\/UZKuFnezFdKhEBd5hMXe8aKAd6ijGDjLARksFuqpi1sS8llC5K1Q+DzktSL\/o64TY4Vuvykiwe\/BAk2SkL9voOtrvU7vfDBcuCPbDJnSBBC0ESpcXeClTBIn6xZ9WaxqoS7sinE\/kUwtWsRd04I7d79\/ouotyNb+mBhTuRsZT12p\/gn4JHXXNUAIpTwchYzGxbfNJ4kxnYBFZWVmvsSqOLFZu1yi5BP3ktA9yhFyWIa5659azRFEKRdXpVHtQVa4IgdhxEqA=",
  683. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  684. }';
  685. $this->fileAccessHelper
  686. ->expects($this->at(0))
  687. ->method('file_get_contents')
  688. ->with(
  689. \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent/core/signature.json'
  690. )
  691. ->willReturn($signatureDataFile);
  692. $this->fileAccessHelper
  693. ->expects($this->at(1))
  694. ->method('file_get_contents')
  695. ->with(
  696. \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent/resources/codesigning/root.crt'
  697. )
  698. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  699. $this->assertSame([], $this->checker->verifyCoreSignature());
  700. }
  701. public function testVerifyCoreSignatureWithModifiedMimetypelistSignatureData() {
  702. $this->environmentHelper
  703. ->expects($this->once())
  704. ->method('getChannel')
  705. ->willReturn('stable');
  706. $this->config
  707. ->expects($this->any())
  708. ->method('getSystemValue')
  709. ->with('integrity.check.disabled', false)
  710. ->willReturn(false);
  711. $this->mimeTypeDetector
  712. ->expects($this->once())
  713. ->method('getOnlyDefaultAliases')
  714. ->willReturn(
  715. [
  716. '_comment' => 'Array of mimetype aliases.',
  717. '_comment2' => 'Any changes you make here will be overwritten on an update of Nextcloud.',
  718. '_comment3' => 'Put any custom mappings in a new file mimetypealiases.json in the config/ folder of Nextcloud',
  719. '_comment4' => 'After any change to mimetypealiases.json run:',
  720. '_comment5' => './occ maintenance:mimetype:update-js',
  721. '_comment6' => 'Otherwise your update won\'t propagate through the system.',
  722. 'application/coreldraw' => 'image',
  723. 'application/epub+zip' => 'text',
  724. 'application/font-sfnt' => 'image',
  725. 'application/font-woff' => 'image',
  726. 'application/gpx+xml' => 'location',
  727. 'application/illustrator' => 'image',
  728. 'application/javascript' => 'text/code',
  729. 'application/json' => 'text/code',
  730. 'application/msaccess' => 'file',
  731. 'application/msexcel' => 'x-office/spreadsheet',
  732. 'application/msonenote' => 'x-office/document',
  733. 'application/mspowerpoint' => 'x-office/presentation',
  734. 'application/msword' => 'x-office/document',
  735. 'application/octet-stream' => 'file',
  736. 'application/postscript' => 'image',
  737. 'application/rss+xml' => 'application/xml',
  738. 'application/vnd.android.package-archive' => 'package/x-generic',
  739. 'application/vnd.lotus-wordpro' => 'x-office/document',
  740. 'application/vnd.garmin.tcx+xml' => 'location',
  741. 'application/vnd.google-earth.kml+xml' => 'location',
  742. 'application/vnd.google-earth.kmz' => 'location',
  743. 'application/vnd.ms-excel' => 'x-office/spreadsheet',
  744. 'application/vnd.ms-excel.addin.macroEnabled.12' => 'x-office/spreadsheet',
  745. 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => 'x-office/spreadsheet',
  746. 'application/vnd.ms-excel.sheet.macroEnabled.12' => 'x-office/spreadsheet',
  747. 'application/vnd.ms-excel.template.macroEnabled.12' => 'x-office/spreadsheet',
  748. 'application/vnd.ms-fontobject' => 'image',
  749. 'application/vnd.ms-powerpoint' => 'x-office/presentation',
  750. 'application/vnd.ms-powerpoint.addin.macroEnabled.12' => 'x-office/presentation',
  751. 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' => 'x-office/presentation',
  752. 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => 'x-office/presentation',
  753. 'application/vnd.ms-powerpoint.template.macroEnabled.12' => 'x-office/presentation',
  754. 'application/vnd.ms-visio.drawing.macroEnabled.12' => 'application/vnd.visio',
  755. 'application/vnd.ms-visio.drawing' => 'application/vnd.visio',
  756. 'application/vnd.ms-visio.stencil.macroEnabled.12' => 'application/vnd.visio',
  757. 'application/vnd.ms-visio.stencil' => 'application/vnd.visio',
  758. 'application/vnd.ms-visio.template.macroEnabled.12' => 'application/vnd.visio',
  759. 'application/vnd.ms-visio.template' => 'application/vnd.visio',
  760. 'application/vnd.ms-word.document.macroEnabled.12' => 'x-office/document',
  761. 'application/vnd.ms-word.template.macroEnabled.12' => 'x-office/document',
  762. 'application/vnd.oasis.opendocument.presentation' => 'x-office/presentation',
  763. 'application/vnd.oasis.opendocument.presentation-template' => 'x-office/presentation',
  764. 'application/vnd.oasis.opendocument.spreadsheet' => 'x-office/spreadsheet',
  765. 'application/vnd.oasis.opendocument.spreadsheet-template' => 'x-office/spreadsheet',
  766. 'application/vnd.oasis.opendocument.text' => 'x-office/document',
  767. 'application/vnd.oasis.opendocument.text-master' => 'x-office/document',
  768. 'application/vnd.oasis.opendocument.text-template' => 'x-office/document',
  769. 'application/vnd.oasis.opendocument.text-web' => 'x-office/document',
  770. 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'x-office/presentation',
  771. 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'x-office/presentation',
  772. 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'x-office/presentation',
  773. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'x-office/spreadsheet',
  774. 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'x-office/spreadsheet',
  775. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'x-office/document',
  776. 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'x-office/document',
  777. 'application/vnd.visio' => 'x-office/document',
  778. 'application/vnd.wordperfect' => 'x-office/document',
  779. 'application/x-7z-compressed' => 'package/x-generic',
  780. 'application/x-bzip2' => 'package/x-generic',
  781. 'application/x-cbr' => 'text',
  782. 'application/x-compressed' => 'package/x-generic',
  783. 'application/x-dcraw' => 'image',
  784. 'application/x-deb' => 'package/x-generic',
  785. 'application/x-fictionbook+xml' => 'text',
  786. 'application/x-font' => 'image',
  787. 'application/x-gimp' => 'image',
  788. 'application/x-gzip' => 'package/x-generic',
  789. 'application/x-iwork-keynote-sffkey' => 'x-office/presentation',
  790. 'application/x-iwork-numbers-sffnumbers' => 'x-office/spreadsheet',
  791. 'application/x-iwork-pages-sffpages' => 'x-office/document',
  792. 'application/x-mobipocket-ebook' => 'text',
  793. 'application/x-perl' => 'text/code',
  794. 'application/x-photoshop' => 'image',
  795. 'application/x-php' => 'text/code',
  796. 'application/x-rar-compressed' => 'package/x-generic',
  797. 'application/x-tar' => 'package/x-generic',
  798. 'application/x-tex' => 'text',
  799. 'application/xml' => 'text/html',
  800. 'application/yaml' => 'text/code',
  801. 'application/zip' => 'package/x-generic',
  802. 'database' => 'file',
  803. 'httpd/unix-directory' => 'dir',
  804. 'text/css' => 'text/code',
  805. 'text/csv' => 'x-office/spreadsheet',
  806. 'text/html' => 'text/code',
  807. 'text/x-c' => 'text/code',
  808. 'text/x-c++src' => 'text/code',
  809. 'text/x-h' => 'text/code',
  810. 'text/x-java-source' => 'text/code',
  811. 'text/x-ldif' => 'text/code',
  812. 'text/x-python' => 'text/code',
  813. 'text/x-shellscript' => 'text/code',
  814. 'web' => 'text/code',
  815. 'application/internet-shortcut' => 'link',
  816. 'application/km' => 'mindmap',
  817. 'application/x-freemind' => 'mindmap',
  818. 'application/vnd.xmind.workbook' => 'mindmap'
  819. ]);
  820. $this->mimeTypeDetector
  821. ->expects($this->once())
  822. ->method('getAllAliases')
  823. ->willReturn(
  824. [
  825. '_comment' => 'Array of mimetype aliases.',
  826. '_comment2' => 'Any changes you make here will be overwritten on an update of Nextcloud.',
  827. '_comment3' => 'Put any custom mappings in a new file mimetypealiases.json in the config/ folder of Nextcloud',
  828. '_comment4' => 'After any change to mimetypealiases.json run:',
  829. '_comment5' => './occ maintenance:mimetype:update-js',
  830. '_comment6' => 'Otherwise your update won\'t propagate through the system.',
  831. 'application/coreldraw' => 'image',
  832. 'application/test' => 'image',
  833. 'application/epub+zip' => 'text',
  834. 'application/font-sfnt' => 'image',
  835. 'application/font-woff' => 'image',
  836. 'application/gpx+xml' => 'location',
  837. 'application/illustrator' => 'image',
  838. 'application/javascript' => 'text/code',
  839. 'application/json' => 'text/code',
  840. 'application/msaccess' => 'file',
  841. 'application/msexcel' => 'x-office/spreadsheet',
  842. 'application/msonenote' => 'x-office/document',
  843. 'application/mspowerpoint' => 'x-office/presentation',
  844. 'application/msword' => 'x-office/document',
  845. 'application/octet-stream' => 'file',
  846. 'application/postscript' => 'image',
  847. 'application/rss+xml' => 'application/xml',
  848. 'application/vnd.android.package-archive' => 'package/x-generic',
  849. 'application/vnd.lotus-wordpro' => 'x-office/document',
  850. 'application/vnd.garmin.tcx+xml' => 'location',
  851. 'application/vnd.google-earth.kml+xml' => 'location',
  852. 'application/vnd.google-earth.kmz' => 'location',
  853. 'application/vnd.ms-excel' => 'x-office/spreadsheet',
  854. 'application/vnd.ms-excel.addin.macroEnabled.12' => 'x-office/spreadsheet',
  855. 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => 'x-office/spreadsheet',
  856. 'application/vnd.ms-excel.sheet.macroEnabled.12' => 'x-office/spreadsheet',
  857. 'application/vnd.ms-excel.template.macroEnabled.12' => 'x-office/spreadsheet',
  858. 'application/vnd.ms-fontobject' => 'image',
  859. 'application/vnd.ms-powerpoint' => 'x-office/presentation',
  860. 'application/vnd.ms-powerpoint.addin.macroEnabled.12' => 'x-office/presentation',
  861. 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' => 'x-office/presentation',
  862. 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => 'x-office/presentation',
  863. 'application/vnd.ms-powerpoint.template.macroEnabled.12' => 'x-office/presentation',
  864. 'application/vnd.ms-visio.drawing.macroEnabled.12' => 'application/vnd.visio',
  865. 'application/vnd.ms-visio.drawing' => 'application/vnd.visio',
  866. 'application/vnd.ms-visio.stencil.macroEnabled.12' => 'application/vnd.visio',
  867. 'application/vnd.ms-visio.stencil' => 'application/vnd.visio',
  868. 'application/vnd.ms-visio.template.macroEnabled.12' => 'application/vnd.visio',
  869. 'application/vnd.ms-visio.template' => 'application/vnd.visio',
  870. 'application/vnd.ms-word.document.macroEnabled.12' => 'x-office/document',
  871. 'application/vnd.ms-word.template.macroEnabled.12' => 'x-office/document',
  872. 'application/vnd.oasis.opendocument.presentation' => 'x-office/presentation',
  873. 'application/vnd.oasis.opendocument.presentation-template' => 'x-office/presentation',
  874. 'application/vnd.oasis.opendocument.spreadsheet' => 'x-office/spreadsheet',
  875. 'application/vnd.oasis.opendocument.spreadsheet-template' => 'x-office/spreadsheet',
  876. 'application/vnd.oasis.opendocument.text' => 'x-office/document',
  877. 'application/vnd.oasis.opendocument.text-master' => 'x-office/document',
  878. 'application/vnd.oasis.opendocument.text-template' => 'x-office/document',
  879. 'application/vnd.oasis.opendocument.text-web' => 'x-office/document',
  880. 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'x-office/presentation',
  881. 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'x-office/presentation',
  882. 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'x-office/presentation',
  883. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'x-office/spreadsheet',
  884. 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'x-office/spreadsheet',
  885. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'x-office/document',
  886. 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'x-office/document',
  887. 'application/vnd.visio' => 'x-office/document',
  888. 'application/vnd.wordperfect' => 'x-office/document',
  889. 'application/x-7z-compressed' => 'package/x-generic',
  890. 'application/x-bzip2' => 'package/x-generic',
  891. 'application/x-cbr' => 'text',
  892. 'application/x-compressed' => 'package/x-generic',
  893. 'application/x-dcraw' => 'image',
  894. 'application/x-deb' => 'package/x-generic',
  895. 'application/x-fictionbook+xml' => 'text',
  896. 'application/x-font' => 'image',
  897. 'application/x-gimp' => 'image',
  898. 'application/x-gzip' => 'package/x-generic',
  899. 'application/x-iwork-keynote-sffkey' => 'x-office/presentation',
  900. 'application/x-iwork-numbers-sffnumbers' => 'x-office/spreadsheet',
  901. 'application/x-iwork-pages-sffpages' => 'x-office/document',
  902. 'application/x-mobipocket-ebook' => 'text',
  903. 'application/x-perl' => 'text/code',
  904. 'application/x-photoshop' => 'image',
  905. 'application/x-php' => 'text/code',
  906. 'application/x-rar-compressed' => 'package/x-generic',
  907. 'application/x-tar' => 'package/x-generic',
  908. 'application/x-tex' => 'text',
  909. 'application/xml' => 'text/html',
  910. 'application/yaml' => 'text/code',
  911. 'application/zip' => 'package/x-generic',
  912. 'database' => 'file',
  913. 'httpd/unix-directory' => 'dir',
  914. 'text/css' => 'text/code',
  915. 'text/csv' => 'x-office/spreadsheet',
  916. 'text/html' => 'text/code',
  917. 'text/x-c' => 'text/code',
  918. 'text/x-c++src' => 'text/code',
  919. 'text/x-h' => 'text/code',
  920. 'text/x-java-source' => 'text/code',
  921. 'text/x-ldif' => 'text/code',
  922. 'text/x-python' => 'text/code',
  923. 'text/x-shellscript' => 'text/code',
  924. 'web' => 'text/code',
  925. 'application/internet-shortcut' => 'link',
  926. 'application/km' => 'mindmap',
  927. 'application/x-freemind' => 'mindmap',
  928. 'application/vnd.xmind.workbook' => 'mindmap'
  929. ]);
  930. $this->environmentHelper
  931. ->expects($this->any())
  932. ->method('getServerRoot')
  933. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/mimetypeListModified');
  934. $signatureDataFile = '{
  935. "hashes": {
  936. "mimetypelist.js": "23a3fa45757b26795f5cf8f94d9e5bce76fc916288a6458679311b312c167adcf4158ccb2c5c3db791fa0b87703b6c5863afb6c9d790b8cbac5ab3ae8c3418fb"
  937. },
  938. "signature": "rqdAbS1evGMhv5vQEhFwDoDgumY1La+xAEgF8TdJjyE1uEjV5442LgnIbolqH5WmGkU4EEjcIJWXEhxbtr7P1EO8WT0v7mVJBmAT0p5Gi3nxz9z9gp7mAbjfBH8McYxNzy92XbdYgiNMqi5tltYRCBXTVw1Rexh9dFc7jmLQIfpAFImR9sQG5eqGUGm+L70o34EToDnEg6Finqj4Ii5aGaGTf+DMz6wZRM2vfeegw5pxgv7EjW4R2dVTGSwwvjQbBSDzMqJHGPXkAlpnqgPDXfSLsRYXVYoRGfD6gXJ8WkjCtceQhW3FG7zMzGykogQtxWDgvbTZsz1PlzBR82UZj144ustqmCNf+ZFSwzjKpQil0hiNZmgmAGPn7frwKbDwE6TAqvqfNbpNy1GcP+eNmTn8C+tmKgyGSkqx67w8NgEn9mmPkubZk6Q/cQ/GIVprY27iPQc5irdV+COi6ZWl+WfO6BNRewlsiAYAe1XQwf4wJ5qGFzKNUd9ovWUfgh61ZthIZEVFcTGMmH4cjymnGxpbqiow4di7RQNuCKTRowmrKAWb58KUGEXxy5Nrr9M8SSn5N232iV6HSEWf5QwoKpZ2Zv9BdTXv0Rzx3MO/NWhj2O0UBmCqL1VI/uem9HoC0751GTnMSk36bIVWflJm6fimVvF7OAvZpZgNKBbtJVs=",
  939. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  940. }';
  941. $this->fileAccessHelper
  942. ->expects($this->at(0))
  943. ->method('file_get_contents')
  944. ->with(
  945. \OC::$SERVERROOT . '/tests/data/integritycheck/mimetypeListModified/core/signature.json'
  946. )
  947. ->willReturn($signatureDataFile);
  948. $this->fileAccessHelper
  949. ->expects($this->at(1))
  950. ->method('file_get_contents')
  951. ->with(
  952. \OC::$SERVERROOT . '/tests/data/integritycheck/mimetypeListModified/resources/codesigning/root.crt'
  953. )
  954. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  955. $this->assertSame([], $this->checker->verifyCoreSignature());
  956. }
  957. public function testVerifyCoreSignatureWithValidSignatureDataAndNotAlphabeticOrder() {
  958. $this->environmentHelper
  959. ->expects($this->once())
  960. ->method('getChannel')
  961. ->willReturn('stable');
  962. $this->config
  963. ->expects($this->any())
  964. ->method('getSystemValue')
  965. ->with('integrity.check.disabled', false)
  966. ->willReturn(false);
  967. $this->environmentHelper
  968. ->expects($this->any())
  969. ->method('getServerRoot')
  970. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  971. $signatureDataFile = '{
  972. "hashes": {
  973. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  974. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  975. },
  976. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  977. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  978. }';
  979. $this->fileAccessHelper
  980. ->expects($this->at(0))
  981. ->method('file_get_contents')
  982. ->with(
  983. \OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json'
  984. )
  985. ->willReturn($signatureDataFile);
  986. $this->fileAccessHelper
  987. ->expects($this->at(1))
  988. ->method('file_get_contents')
  989. ->with(
  990. \OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
  991. )
  992. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  993. $this->assertSame([], $this->checker->verifyCoreSignature());
  994. }
  995. public function testVerifyCoreSignatureWithTamperedSignatureData() {
  996. $this->environmentHelper
  997. ->expects($this->once())
  998. ->method('getChannel')
  999. ->willReturn('stable');
  1000. $this->config
  1001. ->expects($this->any())
  1002. ->method('getSystemValue')
  1003. ->with('integrity.check.disabled', false)
  1004. ->willReturn(false);
  1005. $this->environmentHelper
  1006. ->expects($this->any())
  1007. ->method('getServerRoot')
  1008. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/');
  1009. $signatureDataFile = '{
  1010. "hashes": {
  1011. "AnotherFile.txt": "tampered",
  1012. "subfolder\/file.txt": "tampered"
  1013. },
  1014. "signature": "eXesvDm3pkek12xSwMG10y9suRES79Nye3jYNe5KYq1tTUPqRRNgxmMGAfcUro0zpLeAr2YgHeSMWtglblGOW7pmwGVPZ0O1Y4r1fE6jnep0kW+35PLIaqCorIOnCAtSzDNKBhwd1ow3zW2wC0DFouuEkIO8u5Fw28g8E8dp8zEk1xMblNPy+xtWkmYHrVJ\/dQgun1bYOF2ZFtAzatwndTI\/bGsy1i3Wsl+x6HyWKQdq8y8VObtOqKDH7uERBEpB9DHVyKflj1v1gQuEH6BhaRdATc7ee0MiQdGblraIySwYRdfo2d8i82OVKrenMB3SLwyCvDPyQ9iKpTOnSF52ZBqaqSXKM2N\/RAkweeBFQQCwcHhqxvB0cfbyHcbkOLeCZe\/tsh68IxwTiYgzvLfl7sOZ5arnZbzrPpZmB+hfV2omkoJ1tDwOWz9hEmLLNtfo2OxyUH1m0+XFaC+Gbn4WkVDgf7YZkwUcG+Qoa3oKDNMss8MEyZxewl2iDGZcf402dlidHRprlfmXbAYuVQ08\/a0HxIKYPGh\/nsMGmwnO15CWtFpAbhUA\/D5oRjsIxnvXaMDg0iAFpdu\/5Ffsj7g3EPdBkiQHNYK7YU1RRx609eH0bZyiIYHdUPw7ikLupvrebZmELqi3mqDFO99u4eISlxFJlUbUND3L4BtmWTWrKwI=",
  1015. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  1016. }';
  1017. $this->fileAccessHelper
  1018. ->expects($this->at(0))
  1019. ->method('file_get_contents')
  1020. ->with(
  1021. \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//core/signature.json'
  1022. )
  1023. ->willReturn($signatureDataFile);
  1024. $this->fileAccessHelper
  1025. ->expects($this->at(1))
  1026. ->method('file_get_contents')
  1027. ->with(
  1028. \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//resources/codesigning/root.crt'
  1029. )
  1030. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  1031. $expected = [
  1032. 'EXCEPTION' => [
  1033. 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
  1034. 'message' => 'Signature could not get verified.',
  1035. ]
  1036. ];
  1037. $this->assertSame($expected, $this->checker->verifyCoreSignature());
  1038. }
  1039. public function testVerifyCoreSignatureWithTamperedFiles() {
  1040. $this->environmentHelper
  1041. ->expects($this->once())
  1042. ->method('getChannel')
  1043. ->willReturn('stable');
  1044. $this->config
  1045. ->expects($this->any())
  1046. ->method('getSystemValue')
  1047. ->with('integrity.check.disabled', false)
  1048. ->willReturn(false);
  1049. $this->environmentHelper
  1050. ->expects($this->any())
  1051. ->method('getServerRoot')
  1052. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/');
  1053. $signatureDataFile = '{
  1054. "hashes": {
  1055. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  1056. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  1057. },
  1058. "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
  1059. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
  1060. }';
  1061. $this->fileAccessHelper
  1062. ->expects($this->at(0))
  1063. ->method('file_get_contents')
  1064. ->with(
  1065. \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//core/signature.json'
  1066. )
  1067. ->willReturn($signatureDataFile);
  1068. $this->fileAccessHelper
  1069. ->expects($this->at(1))
  1070. ->method('file_get_contents')
  1071. ->with(
  1072. \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//resources/codesigning/root.crt'
  1073. )
  1074. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  1075. $expected = [
  1076. 'INVALID_HASH' => [
  1077. 'AnotherFile.txt' => [
  1078. 'expected' => '1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112',
  1079. 'current' => '7322348ba269c6d5522efe02f424fa3a0da319a7cd9c33142a5afe32a2d9af2da3a411f086fcfc96ff4301ea566f481dba0960c2abeef3594c4d930462f6584c',
  1080. ],
  1081. ],
  1082. 'FILE_MISSING' => [
  1083. 'subfolder/file.txt' => [
  1084. 'expected' => '410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b',
  1085. 'current' => '',
  1086. ],
  1087. ],
  1088. 'EXTRA_FILE' => [
  1089. 'UnecessaryFile' => [
  1090. 'expected' => '',
  1091. 'current' => 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
  1092. ],
  1093. ],
  1094. ];
  1095. $this->assertSame($expected, $this->checker->verifyCoreSignature());
  1096. }
  1097. public function testVerifyCoreWithInvalidCertificate() {
  1098. $this->environmentHelper
  1099. ->expects($this->once())
  1100. ->method('getChannel')
  1101. ->willReturn('stable');
  1102. $this->config
  1103. ->expects($this->any())
  1104. ->method('getSystemValue')
  1105. ->with('integrity.check.disabled', false)
  1106. ->willReturn(false);
  1107. $this->environmentHelper
  1108. ->expects($this->any())
  1109. ->method('getServerRoot')
  1110. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  1111. $signatureDataFile = '{
  1112. "hashes": {
  1113. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  1114. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  1115. },
  1116. "signature": "eXesvDm3pkek12xSwMG10y9suRES79Nye3jYNe5KYq1tTUPqRRNgxmMGAfcUro0zpLeAr2YgHeSMWtglblGOW7pmwGVPZ0O1Y4r1fE6jnep0kW+35PLIaqCorIOnCAtSzDNKBhwd1ow3zW2wC0DFouuEkIO8u5Fw28g8E8dp8zEk1xMblNPy+xtWkmYHrVJ\/dQgun1bYOF2ZFtAzatwndTI\/bGsy1i3Wsl+x6HyWKQdq8y8VObtOqKDH7uERBEpB9DHVyKflj1v1gQuEH6BhaRdATc7ee0MiQdGblraIySwYRdfo2d8i82OVKrenMB3SLwyCvDPyQ9iKpTOnSF52ZBqaqSXKM2N\/RAkweeBFQQCwcHhqxvB0cfbyHcbkOLeCZe\/tsh68IxwTiYgzvLfl7sOZ5arnZbzrPpZmB+hfV2omkoJ1tDwOWz9hEmLLNtfo2OxyUH1m0+XFaC+Gbn4WkVDgf7YZkwUcG+Qoa3oKDNMss8MEyZxewl2iDGZcf402dlidHRprlfmXbAYuVQ08\/a0HxIKYPGh\/nsMGmwnO15CWtFpAbhUA\/D5oRjsIxnvXaMDg0iAFpdu\/5Ffsj7g3EPdBkiQHNYK7YU1RRx609eH0bZyiIYHdUPw7ikLupvrebZmELqi3mqDFO99u4eISlxFJlUbUND3L4BtmWTWrKwI=",
  1117. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUPYoweUxCPqbDW4ntuh7QvgyqSrgwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIyNDIwNloXDTE2MTEwMzIyNDIwNlowDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJui3nDbjOIjxNnthdBZplphujsN6u8K\r\nQ\/62zAuSwzXVp0+3IMgM\/2sepklVE8YfCyVJ5+SUJqnqHoUWVRVfs8jL0wW6nrHM\r\n\/lsscAguWCee4iAdNOqI9kq4+DUau8J45e62XA9mrAo\/8\/NKzFE2y2WduDoQZcm+\r\n8+dwcUUHXw2jl8dfrmvEMYSqTNDdb4rGmQpeV+dr9BLqr+x03U1Q08qCG9j7mSOz\r\ncvJENjOvC5uzAh5LCuCgxqG4o+mPzB0FtNnwoRRu6IsF3Y3KacRqPc30fB\/iXDn5\r\nBPr14uNxTTYWoZJ1F0tZrLzRbXdjJJOC+dnQurTtXWZ8WjPB1BWQYK7fW6t82mkN\r\n2Qe2xen99gs9nX5yY\/sHM3TKSJdM7AVCEv\/emW3gNjkvWTtRlN\/Nc7X2ckNwXcvo\r\n0yi3fSPjzXpDgLbhp1FzrMlHDn1VzmRT3r8wLByWa\/hsxrJDsBzwunMJYhXhmeKb\r\n3wX0tN\/EUJTWBntpwVOIGnRPD51oBoQUOMaEAq\/kz8PgN181bWZkJbRuf+FWkijQ\r\no+HR2lVF1jWXXst5Uc+s9HN81Uly7X4O9MMg0QxT4+wymtGDs6AOkwMi9rgBTrRB\r\n3tLU3XL2UIwRXgmd8cPtTu\/I6Bm7LdyaYtZ3yJTxRewq3nZdWypqBhD8uhpIYVkf\r\no4bxmGkVAQVTAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAKKAX5EHgU1grODnJ0of\r\nspFpgB1K67YvclNUyuU6NQ6zBJx1\/w1RnM7uxLcxiiWj1BbUhwZQ0ojmEHeUyi6O\r\nGrDVajwhTccDMmja3u5adhEncx65\/H+lD85IPRRkS2qBDssMDdJHhZ0uI+40nI7M\r\nMq1kFjl+6wiuqZXqps66DuLbk45g\/ZlrFIrIo3Ix5vj0OVqwT+gO4LYirJK6KgVS\r\nUttbcEsc\/yKU9ThnM8\/n4m2jstZXfzKPgOsJrQcZrFOtpj+CWmBzVElBSPlDT3Nh\r\nHSgOeTFJ8bQBxj2iG5dLA+JZJQKxyJ1gy2ZtxIJ2GyvLtSe8NUSqvfPWOaAKEUV2\r\ngniytnEFLr+PcD+9EGux6jZNuj6HmtWVThTfD5VGFmtlVU2z71ZRYY0kn6J3mmFc\r\nS2ecEcCUwqG5YNLncEUCyZhC2klWql2SHyGctCEyWWY7ikIDjVzYt2EbcFvLNBnP\r\ntybN1TYHRRZxlug00CCoOE9EZfk46FkZpDvU6KmqJRofkNZ5sj+SffyGcwYwNrDH\r\nKqe8m+9lHf3CRTIDeMu8r2xl1I6M6ZZfjabbmVP9Jd6WN4s6f1FlXDWzhlT1N0Qw\r\nGzJj6xB+SPtS3UV05tBlvbfA4e06D5G9uD7Q8ONcINtMS0xsSJ2oo82AqlpvlF\/q\r\noj7YKHsaTVGA+FxBktZHfoxD\r\n-----END CERTIFICATE-----"
  1118. }';
  1119. $this->fileAccessHelper
  1120. ->expects($this->at(0))
  1121. ->method('file_get_contents')
  1122. ->with(
  1123. \OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json'
  1124. )
  1125. ->willReturn($signatureDataFile);
  1126. $this->fileAccessHelper
  1127. ->expects($this->at(1))
  1128. ->method('file_get_contents')
  1129. ->with(
  1130. \OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
  1131. )
  1132. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  1133. $expected = [
  1134. 'EXCEPTION' => [
  1135. 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
  1136. 'message' => 'Certificate is not valid.',
  1137. ]
  1138. ];
  1139. $this->assertSame($expected, $this->checker->verifyCoreSignature());
  1140. }
  1141. public function testVerifyCoreWithDifferentScope() {
  1142. $this->environmentHelper
  1143. ->expects($this->once())
  1144. ->method('getChannel')
  1145. ->willReturn('stable');
  1146. $this->config
  1147. ->expects($this->any())
  1148. ->method('getSystemValue')
  1149. ->with('integrity.check.disabled', false)
  1150. ->willReturn(false);
  1151. $this->environmentHelper
  1152. ->expects($this->any())
  1153. ->method('getServerRoot')
  1154. ->willReturn(\OC::$SERVERROOT . '/tests/data/integritycheck/app/');
  1155. $signatureDataFile = '{
  1156. "hashes": {
  1157. "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
  1158. "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
  1159. },
  1160. "signature": "EL49UaSeyMAqyMtqId+tgOhhwgOevPZsRLX4j2blnybAB6fN07z0936JqZV7+eMPiE30Idx+UCY6rCFN531Kqe9vAOCdgtHUSOjjKyKc+lvULESlMb6YQcrZrvDlEMMjzjH49ewG7Ai8sNN6HrRUd9U8ws+ewSkW2DOOBItj\/21RBnkrSt+2AtGXGigEvuTm57HrCYDj8\/lSkumC2GVkjLUHeLOKYo4PRNOr6yP5mED5v7zo66AWvXl2fKv54InZcdxsAk35lyK9DGZbk\/027ZRd0AOHT3LImRLvQ+8EAg3XLlRUy0hOFGgPC+jYonMzgYvsAXAXi2j8LnLJlsLwpFwu1k1B+kZVPMumKZvP9OvJb70EirecXmz62V+Jiyuaq7ne4y7Kp5gKZT\/T8SeZ0lFtCmPfYyzBB0y8s5ldmTTmdVYHs54t\/OCCW82HzQZxnFNPzDTRa8HglsaMKrqPtW59+R4UvRKSWhB8M\/Ah57qgzycvPV4KMz\/FbD4l\/\/9chRKSlCfc2k3b8ZSHNmi+EzCKgJjWIoKdgN1yax94puU8jfn8UW+G7H9Y1Jsf\/jox6QLyYEgtV1vOHY2xLT7fVs2vhyvkN2MNjJnmQ70gFG5Qz2lBz5wi6ZpB+tOfCcpbLxWAkoWoIrmC\/Ilqh7mfmRZ43g5upjkepHNd93ONuY8=",
  1161. "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEwTCCAqmgAwIBAgIUWv0iujufs5lUr0svCf\/qTQvoyKAwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIyNDk1M1oXDTE2MTEwMzIyNDk1M1owEjEQMA4GA1UEAwwHU29tZUFwcDCCAiIw\r\nDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK8q0x62agGSRBqeWsaeEwFfepMk\r\nF8cAobMMi50qHCv9IrOn\/ZH9l52xBrbIkErVmRjmly0d4JhD8Ymhidsh9ONKYl\/j\r\n+ishsZDM8eNNdp3Ew+fEYVvY1W7mR1qU24NWj0bzVsClI7hvPVIuw7AjfBDq1C5+\r\nA+ZSLSXYvOK2cEWjdxQfuNZwEZSjmA63DUllBIrm35IaTvfuyhU6BW9yHZxmb8+M\r\nw0xDv30D5UkE\/2N7Pa\/HQJLxCR+3zKibRK3nUyRDLSXxMkU9PnFNaPNX59VPgyj4\r\nGB1CFSToldJVPF4pzh7p36uGXZVxs8m3LFD4Ol8mhi7jkxDZjqFN46gzR0r23Py6\r\ndol9vfawGIoUwp9LvL0S7MvdRY0oazLXwClLP4OQ17zpSMAiCj7fgNT661JamPGj\r\nt5O7Zn2wA7I4ddDS\/HDTWCu98Zwc9fHIpsJPgCZ9awoqxi4Mnf7Pk9g5nnXhszGC\r\ncxxIASQKM+GhdzoRxKknax2RzUCwCzcPRtCj8AQT\/x\/mqN3PfRmlnFBNACUw9bpZ\r\nSOoNq2pCF9igftDWpSIXQ38pVpKLWowjjg3DVRmVKBgivHnUnVLyzYBahHPj0vaz\r\ntFtUFRaqXDnt+4qyUGyrT5h5pjZaTcHIcSB4PiarYwdVvgslgwnQzOUcGAzRWBD4\r\n6jV2brP5vFY3g6iPAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBACTY3CCHC+Z28gCf\r\nFWGKQ3wAKs+k4+0yoti0qm2EKX7rSGQ0PHSas6uW79WstC4Rj+DYkDtIhGMSg8FS\r\nHVGZHGBCc0HwdX+BOAt3zi4p7Sf3oQef70\/4imPoKxbAVCpd\/cveVcFyDC19j1yB\r\nBapwu87oh+muoeaZxOlqQI4UxjBlR\/uRSMhOn2UGauIr3dWJgAF4pGt7TtIzt+1v\r\n0uA6FtN1Y4R5O8AaJPh1bIG0CVvFBE58esGzjEYLhOydgKFnEP94kVPgJD5ds9C3\r\npPhEpo1dRpiXaF7WGIV1X6DI\/ipWvfrF7CEy6I\/kP1InY\/vMDjQjeDnJ\/VrXIWXO\r\nyZvHXVaN\/m+1RlETsH7YO\/QmxRue9ZHN3gvvWtmpCeA95sfpepOk7UcHxHZYyQbF\r\n49\/au8j+5tsr4A83xzsT1JbcKRxkAaQ7WDJpOnE5O1+H0fB+BaLakTg6XX9d4Fo7\r\n7Gin7hVWX7pL+JIyxMzME3LhfI61+CRcqZQIrpyaafUziPQbWIPfEs7h8tCOWyvW\r\nUO8ZLervYCB3j44ivkrxPlcBklDCqqKKBzDP9dYOtS\/P4RB1NkHA9+NTvmBpTonS\r\nSFXdg9fFMD7VfjDE3Vnk+8DWkVH5wBYowTAD7w9Wuzr7DumiAULexnP\/Y7xwxLv7\r\n4B+pXTAcRK0zECDEaX3npS8xWzrB\r\n-----END CERTIFICATE-----"
  1162. }';
  1163. $this->fileAccessHelper
  1164. ->expects($this->at(0))
  1165. ->method('file_get_contents')
  1166. ->with(
  1167. \OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json'
  1168. )
  1169. ->willReturn($signatureDataFile);
  1170. $this->fileAccessHelper
  1171. ->expects($this->at(1))
  1172. ->method('file_get_contents')
  1173. ->with(
  1174. \OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
  1175. )
  1176. ->willReturn(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt'));
  1177. $expected = [
  1178. 'EXCEPTION' => [
  1179. 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
  1180. 'message' => 'Certificate is not valid for required scope. (Requested: core, current: CN=SomeApp)',
  1181. ]
  1182. ];
  1183. $this->assertSame($expected, $this->checker->verifyCoreSignature());
  1184. }
  1185. public function testRunInstanceVerification() {
  1186. $this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
  1187. ->setConstructorArgs([
  1188. $this->environmentHelper,
  1189. $this->fileAccessHelper,
  1190. $this->appLocator,
  1191. $this->config,
  1192. $this->cacheFactory,
  1193. $this->appManager,
  1194. $this->mimeTypeDetector,
  1195. ])
  1196. ->setMethods([
  1197. 'verifyCoreSignature',
  1198. 'verifyAppSignature',
  1199. ])
  1200. ->getMock();
  1201. $this->checker
  1202. ->expects($this->at(0))
  1203. ->method('verifyCoreSignature');
  1204. $this->appLocator
  1205. ->expects($this->at(0))
  1206. ->method('getAllApps')
  1207. ->willReturn([
  1208. 'files',
  1209. 'calendar',
  1210. 'contacts',
  1211. 'dav',
  1212. ]);
  1213. $this->appManager
  1214. ->expects($this->at(0))
  1215. ->method('isShipped')
  1216. ->with('files')
  1217. ->willReturn(true);
  1218. $this->checker
  1219. ->expects($this->at(1))
  1220. ->method('verifyAppSignature')
  1221. ->with('files');
  1222. $this->appManager
  1223. ->expects($this->at(1))
  1224. ->method('isShipped')
  1225. ->with('calendar')
  1226. ->willReturn(false);
  1227. $this->appLocator
  1228. ->expects($this->at(1))
  1229. ->method('getAppPath')
  1230. ->with('calendar')
  1231. ->willReturn('/apps/calendar');
  1232. $this->fileAccessHelper
  1233. ->expects($this->at(0))
  1234. ->method('file_exists')
  1235. ->with('/apps/calendar/appinfo/signature.json')
  1236. ->willReturn(true);
  1237. $this->checker
  1238. ->expects($this->at(2))
  1239. ->method('verifyAppSignature')
  1240. ->with('calendar');
  1241. $this->appManager
  1242. ->expects($this->at(2))
  1243. ->method('isShipped')
  1244. ->with('contacts')
  1245. ->willReturn(false);
  1246. $this->appLocator
  1247. ->expects($this->at(2))
  1248. ->method('getAppPath')
  1249. ->with('contacts')
  1250. ->willReturn('/apps/contacts');
  1251. $this->fileAccessHelper
  1252. ->expects($this->at(1))
  1253. ->method('file_exists')
  1254. ->with('/apps/contacts/appinfo/signature.json')
  1255. ->willReturn(false);
  1256. $this->appManager
  1257. ->expects($this->at(3))
  1258. ->method('isShipped')
  1259. ->with('dav')
  1260. ->willReturn(true);
  1261. $this->checker
  1262. ->expects($this->at(3))
  1263. ->method('verifyAppSignature')
  1264. ->with('dav');
  1265. $this->config
  1266. ->expects($this->once())
  1267. ->method('deleteAppValue')
  1268. ->with('core', 'oc.integritycheck.checker');
  1269. $this->checker->runInstanceVerification();
  1270. }
  1271. public function testVerifyAppSignatureWithoutSignatureDataAndCodeCheckerDisabled() {
  1272. $this->environmentHelper
  1273. ->expects($this->once())
  1274. ->method('getChannel')
  1275. ->willReturn('stable');
  1276. $this->config
  1277. ->expects($this->any())
  1278. ->method('getSystemValue')
  1279. ->with('integrity.check.disabled', false)
  1280. ->willReturn(true);
  1281. $expected = [];
  1282. $this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp'));
  1283. }
  1284. /**
  1285. * @return array
  1286. */
  1287. public function channelDataProvider() {
  1288. return [
  1289. ['stable', true],
  1290. ['git', false],
  1291. ];
  1292. }
  1293. /**
  1294. * @param string $channel
  1295. * @param bool $isCodeSigningEnforced
  1296. * @dataProvider channelDataProvider
  1297. */
  1298. public function testIsCodeCheckEnforced($channel, $isCodeSigningEnforced) {
  1299. $this->environmentHelper
  1300. ->expects($this->once())
  1301. ->method('getChannel')
  1302. ->willReturn($channel);
  1303. $this->config
  1304. ->expects($this->any())
  1305. ->method('getSystemValue')
  1306. ->with('integrity.check.disabled', false)
  1307. ->willReturn(false);
  1308. $this->assertSame($isCodeSigningEnforced, $this->checker->isCodeCheckEnforced());
  1309. }
  1310. /**
  1311. * @param string $channel
  1312. * @dataProvider channelDataProvider
  1313. */
  1314. public function testIsCodeCheckEnforcedWithDisabledConfigSwitch($channel) {
  1315. $this->environmentHelper
  1316. ->expects($this->once())
  1317. ->method('getChannel')
  1318. ->willReturn($channel);
  1319. $this->config
  1320. ->expects($this->any())
  1321. ->method('getSystemValue')
  1322. ->with('integrity.check.disabled', false)
  1323. ->willReturn(true);
  1324. $this->assertFalse(self::invokePrivate($this->checker, 'isCodeCheckEnforced'));
  1325. }
  1326. }