diff --git a/config/config.sample.php b/config/config.sample.php
index 20b7a55d226f..a1c8ad36f642 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -1231,6 +1231,18 @@
'.snapshot',
'~snapshot',
),
+/**
+ * Exclude directories from the integrity checker command
+ */
+'integrity.excluded.files' =>
+ array (
+ '.DS_Store',
+ 'Thumbs.db',
+ '.directory',
+ '.webapp',
+ '.htaccess',
+ '.user.ini',
+ ),
/**
* Define a default folder for shared files and folders other than root.
*/
diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php
index 0852a5734b6d..9b46b290dd25 100644
--- a/lib/private/IntegrityCheck/Checker.php
+++ b/lib/private/IntegrityCheck/Checker.php
@@ -230,7 +230,7 @@ private function generateHashes(\RecursiveIteratorIterator $iterator,
* @param array $hashes
* @param X509 $certificate
* @param RSA $privateKey
- * @return string
+ * @return array
*/
private function createSignatureData(array $hashes,
X509 $certificate,
@@ -382,6 +382,9 @@ private function verify($signaturePath, $basePath, $certificateCN, $force = fals
throw new InvalidSignatureException('Signature could not get verified.');
}
+ //Exclude files which shouldn't fall for comparison
+ $excludeFiles = $this->config->getSystemValue('integrity.excluded.files', []);
+
// Compare the list of files which are not identical
$currentInstanceHashes = $this->generateHashes($this->getFolderIterator($basePath), $basePath);
$differencesA = array_diff($expectedHashes, $currentInstanceHashes);
@@ -389,6 +392,10 @@ private function verify($signaturePath, $basePath, $certificateCN, $force = fals
$differences = array_unique(array_merge($differencesA, $differencesB));
$differenceArray = [];
foreach($differences as $filename => $hash) {
+ //If filename in exclude files list, then ignore it
+ if (in_array($filename, $excludeFiles, true)) {
+ continue;
+ }
// Check if file should not exist in the new signature table
if(!array_key_exists($filename, $expectedHashes)) {
$differenceArray['EXTRA_FILE'][$filename]['expected'] = '';
diff --git a/tests/lib/IntegrityCheck/CheckerTest.php b/tests/lib/IntegrityCheck/CheckerTest.php
index 4ff864676f22..008f36660844 100644
--- a/tests/lib/IntegrityCheck/CheckerTest.php
+++ b/tests/lib/IntegrityCheck/CheckerTest.php
@@ -159,15 +159,17 @@ public function testVerifyAppSignatureWithoutSignatureData() {
}
public function testVerifyAppSignatureWithValidSignatureData() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
- ->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
$this->appLocator
->expects($this->once())
@@ -249,15 +251,17 @@ public function testVerifyAppSignatureWithTamperedSignatureData() {
}
public function testVerifyAppSignatureWithTamperedFiles() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
- ->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
$this->appLocator
->expects($this->once())
@@ -313,15 +317,17 @@ public function testVerifyAppSignatureWithTamperedFiles() {
}
public function testVerifyAppSignatureWithTamperedFilesAndAlternatePath() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
- ->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
$this->appLocator
->expects($this->never())
@@ -422,15 +428,17 @@ public function testVerifyAppWithDifferentScope() {
}
public function testVerifyAppWithDifferentScopeAndAlwaysTrustedCore() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
- ->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
$this->appLocator
->expects($this->once())
@@ -626,15 +634,17 @@ public function testVerifyCoreSignatureWithoutSignatureData() {
}
public function testVerifyCoreSignatureWithValidSignatureData() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
- ->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
$this->environmentHelper
->expects($this->any())
@@ -667,15 +677,17 @@ public function testVerifyCoreSignatureWithValidSignatureData() {
}
public function testVerifyCoreSignatureWithValidModifiedHtaccessAndUserIniSignatureData() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->will($this->returnValueMap($map));
$this->environmentHelper
->expects($this->any())
@@ -709,15 +721,17 @@ public function testVerifyCoreSignatureWithValidModifiedHtaccessAndUserIniSignat
}
public function testVerifyCoreSignatureWithValidSignatureDataAndNotAlphabeticOrder() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
- ->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
$this->environmentHelper
->expects($this->any())
@@ -797,15 +811,17 @@ public function testVerifyCoreSignatureWithTamperedSignatureData() {
}
public function testVerifyCoreSignatureWithTamperedFiles() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array()],
+ ];
$this->environmentHelper
->expects($this->once())
->method('getChannel')
->will($this->returnValue('stable'));
$this->config
- ->expects($this->any())
- ->method('getSystemValue')
- ->with('integrity.check.disabled', false)
- ->will($this->returnValue(false));
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
$this->environmentHelper
->expects($this->any())
@@ -858,6 +874,64 @@ public function testVerifyCoreSignatureWithTamperedFiles() {
$this->assertSame($expected, $this->checker->verifyCoreSignature());
}
+ public function testVerifyCoreSignatureWithTamperedFilesExclude() {
+ $map = [
+ ['integrity.check.disabled', false, false],
+ ['integrity.excluded.files', [], array('AnotherFile.txt')],
+ ];
+ $this->environmentHelper
+ ->expects($this->once())
+ ->method('getChannel')
+ ->will($this->returnValue('stable'));
+ $this->config
+ ->method('getSystemValue')
+ ->will($this->returnValueMap($map));
+
+ $this->environmentHelper
+ ->expects($this->any())
+ ->method('getServerRoot')
+ ->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/'));
+ $signatureDataFile = '{
+ "hashes": {
+ "AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
+ "subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
+ },
+ "signature": "dYoohBaWIFR\/To1FXEbMQB5apUhVYlEauBGSPo12nq84wxWkBx2EM3KDRgkB5Sub2tr0CgmAc2EVjPhKIEzAam26cyUb48bJziz1V6wvW7z4GZAfaJpzLkyHdSfV5117VSf5w1rDcAeZDXfGUaaNEJPWytaF4ZIxVge7f3NGshHy4odFVPADy\/u6c43BWvaOtJ4m3aJQbP6sxCO9dxwcm5yJJJR3n36jfh229sdWBxyl8BhwhH1e1DEv78\/aiL6ckKFPVNzx01R6yDFt3TgEMR97YZ\/R6lWiXG+dsJ305jNFlusLu518zBUvl7g5yjzGN778H29b2C8VLZKmi\/h1CH9jGdD72fCqCYdenD2uZKzb6dsUtXtvBmVcVT6BUGz41W1pkkEEB+YJpMrHILIxAiHRGv1+aZa9\/Oz8LWFd+BEUQjC2LJgojPnpzaG\/msw1nBkX16NNVDWWtJ25Bc\/r\/mG46rwjWB\/cmV6Lwt6KODiqlxgrC4lm9ALOCEWw+23OcYhLwNfQTYevXqHqsFfXOkhUnM8z5vDUb\/HBraB1DjFXN8iLK+1YewD4P495e+SRzrR79Oi3F8SEqRIzRLfN2rnW1BTms\/wYsz0p67cup1Slk1XlNmHwbWX25NVd2PPlLOvZRGoqcKFpIjC5few8THiZfyjiNFwt3RM0AFdZcXY=",
+ "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-----"
+}';
+ $this->fileAccessHelper
+ ->expects($this->at(0))
+ ->method('file_get_contents')
+ ->with(
+ \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//core/signature.json'
+ )
+ ->will($this->returnValue($signatureDataFile));
+ $this->fileAccessHelper
+ ->expects($this->at(1))
+ ->method('file_get_contents')
+ ->with(
+ \OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//resources/codesigning/root.crt'
+ )
+ ->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
+
+ $expected = [
+ 'FILE_MISSING' => [
+ 'subfolder/file.txt' => [
+ 'expected' => '410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b',
+ 'current' => '',
+ ],
+ ],
+ 'EXTRA_FILE' => [
+ 'UnecessaryFile' => [
+ 'expected' => '',
+ 'current' => 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
+ ],
+ ],
+
+ ];
+ $this->assertSame($expected, $this->checker->verifyCoreSignature());
+ }
+
public function testVerifyCoreWithInvalidCertificate() {
$this->environmentHelper
->expects($this->once())
diff --git a/tests/phpunit-autotest.xml b/tests/phpunit-autotest.xml
index c6f7b1f07d3d..2b8140f9beb7 100644
--- a/tests/phpunit-autotest.xml
+++ b/tests/phpunit-autotest.xml
@@ -34,6 +34,7 @@
../tests
../build
../lib/composer
+ ../config/config.sample.php