Merge pull request #20285 from owncloud/add-integrity-checker
Add code integrity checker foundation
This commit is contained in:
commit
74e8c25a5b
43 changed files with 3262 additions and 11 deletions
|
@ -47,6 +47,7 @@ if (OC::checkUpgrade(false)) {
|
|||
$updater = new \OC\Updater(
|
||||
\OC::$server->getHTTPHelper(),
|
||||
$config,
|
||||
\OC::$server->getIntegrityCodeChecker(),
|
||||
$logger
|
||||
);
|
||||
$incompatibleApps = [];
|
||||
|
@ -108,6 +109,12 @@ if (OC::checkUpgrade(false)) {
|
|||
$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
|
||||
$eventSource->send('success', (string)$l->t('Reset log level to "%s"', [ $logLevelName ]));
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($eventSource, $l) {
|
||||
$eventSource->send('success', (string)$l->t('Starting code integrity check'));
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($eventSource, $l) {
|
||||
$eventSource->send('success', (string)$l->t('Finished code integrity check'));
|
||||
});
|
||||
|
||||
try {
|
||||
$updater->upgrade();
|
||||
|
|
98
core/command/integrity/signapp.php
Normal file
98
core/command/integrity/signapp.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Core\Command\Integrity;
|
||||
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\File\X509;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Class SignApp
|
||||
*
|
||||
* @package OC\Core\Command\Integrity
|
||||
*/
|
||||
class SignApp extends Command {
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
/** @var FileAccessHelper */
|
||||
private $fileAccessHelper;
|
||||
|
||||
/**
|
||||
* @param Checker $checker
|
||||
* @param FileAccessHelper $fileAccessHelper
|
||||
*/
|
||||
public function __construct(Checker $checker,
|
||||
FileAccessHelper $fileAccessHelper) {
|
||||
parent::__construct(null);
|
||||
$this->checker = $checker;
|
||||
$this->fileAccessHelper = $fileAccessHelper;
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this
|
||||
->setName('integrity:sign-app')
|
||||
->setDescription('Sign app using a private key.')
|
||||
->addOption('appId', null, InputOption::VALUE_REQUIRED, 'Application to sign')
|
||||
->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
|
||||
->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc }
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$appId = $input->getOption('appId');
|
||||
$privateKeyPath = $input->getOption('privateKey');
|
||||
$keyBundlePath = $input->getOption('certificate');
|
||||
if(is_null($appId) || is_null($privateKeyPath) || is_null($keyBundlePath)) {
|
||||
$output->writeln('--appId, --privateKey and --certificate are required.');
|
||||
return null;
|
||||
}
|
||||
|
||||
$privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath);
|
||||
$keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath);
|
||||
|
||||
if($privateKey === false) {
|
||||
$output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath));
|
||||
return null;
|
||||
}
|
||||
|
||||
if($keyBundle === false) {
|
||||
$output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath));
|
||||
return null;
|
||||
}
|
||||
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($privateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$x509->setPrivateKey($rsa);
|
||||
$this->checker->writeAppSignature($appId, $x509, $rsa);
|
||||
|
||||
$output->writeln('Successfully signed "'.$appId.'"');
|
||||
}
|
||||
}
|
98
core/command/integrity/signcore.php
Normal file
98
core/command/integrity/signcore.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Core\Command\Integrity;
|
||||
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OC\IntegrityCheck\Helpers\EnvironmentHelper;
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\File\X509;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use OCP\IConfig;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Class SignCore
|
||||
*
|
||||
* @package OC\Core\Command\Integrity
|
||||
*/
|
||||
class SignCore extends Command {
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
/** @var FileAccessHelper */
|
||||
private $fileAccessHelper;
|
||||
|
||||
/**
|
||||
* @param Checker $checker
|
||||
* @param FileAccessHelper $fileAccessHelper
|
||||
*/
|
||||
public function __construct(Checker $checker,
|
||||
FileAccessHelper $fileAccessHelper) {
|
||||
parent::__construct(null);
|
||||
$this->checker = $checker;
|
||||
$this->fileAccessHelper = $fileAccessHelper;
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this
|
||||
->setName('integrity:sign-core')
|
||||
->setDescription('Sign core using a private key.')
|
||||
->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
|
||||
->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc }
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$privateKeyPath = $input->getOption('privateKey');
|
||||
$keyBundlePath = $input->getOption('certificate');
|
||||
if(is_null($privateKeyPath) || is_null($keyBundlePath)) {
|
||||
$output->writeln('--privateKey and --certificate are required.');
|
||||
return null;
|
||||
}
|
||||
|
||||
$privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath);
|
||||
$keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath);
|
||||
|
||||
if($privateKey === false) {
|
||||
$output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath));
|
||||
return null;
|
||||
}
|
||||
|
||||
if($keyBundle === false) {
|
||||
$output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath));
|
||||
return null;
|
||||
}
|
||||
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($privateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$x509->setPrivateKey($rsa);
|
||||
$this->checker->writeCoreSignature($x509, $rsa);
|
||||
|
||||
$output->writeln('Successfully signed "core"');
|
||||
}
|
||||
}
|
|
@ -53,6 +53,7 @@ class Upgrade extends Command {
|
|||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param ILogger $logger
|
||||
*/
|
||||
public function __construct(IConfig $config, ILogger $logger) {
|
||||
parent::__construct();
|
||||
|
@ -122,9 +123,12 @@ class Upgrade extends Command {
|
|||
}
|
||||
|
||||
$self = $this;
|
||||
$updater = new Updater(\OC::$server->getHTTPHelper(),
|
||||
$this->config,
|
||||
$this->logger);
|
||||
$updater = new Updater(
|
||||
\OC::$server->getHTTPHelper(),
|
||||
$this->config,
|
||||
\OC::$server->getIntegrityCodeChecker(),
|
||||
$this->logger
|
||||
);
|
||||
|
||||
$updater->setSimulateStepEnabled($simulateStepEnabled);
|
||||
$updater->setUpdateStepEnabled($updateStepEnabled);
|
||||
|
|
38
core/js/integritycheck-failed-notification.js
Normal file
38
core/js/integritycheck-failed-notification.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* @author Lukas Reschke
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* This gets only loaded if the integrity check has failed and then shows a notification
|
||||
*/
|
||||
$(document).ready(function(){
|
||||
var text = t(
|
||||
'core',
|
||||
'<a href="{docUrl}">There were problems with the code integrity check. More information…</a>',
|
||||
{
|
||||
docUrl: OC.generateUrl('/settings/admin#security-warning')
|
||||
}
|
||||
);
|
||||
|
||||
OC.Notification.showHtml(
|
||||
text,
|
||||
{
|
||||
isHTML: true
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
@ -104,6 +104,20 @@
|
|||
type: OC.SetupChecks.MESSAGE_TYPE_WARNING
|
||||
});
|
||||
}
|
||||
if(!data.hasPassedCodeIntegrityCheck) {
|
||||
messages.push({
|
||||
msg: t(
|
||||
'core',
|
||||
'Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our <a href="{docLink}">documentation</a>. (<a href="{codeIntegrityDownloadEndpoint}">List of invalid files…</a> / <a href="{rescanEndpoint}">Rescan…</a>)',
|
||||
{
|
||||
docLink: data.codeIntegrityCheckerDocumentation,
|
||||
codeIntegrityDownloadEndpoint: OC.generateUrl('/settings/integrity/failed'),
|
||||
rescanEndpoint: OC.generateUrl('/settings/integrity/rescan?requesttoken={requesttoken}', {'requesttoken': OC.requestToken})
|
||||
}
|
||||
),
|
||||
type: OC.SetupChecks.MESSAGE_TYPE_ERROR
|
||||
});
|
||||
}
|
||||
} else {
|
||||
messages.push({
|
||||
msg: t('core', 'Error occurred while checking server setup'),
|
||||
|
|
|
@ -75,6 +75,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
memcacheDocs: 'https://doc.owncloud.org/server/go.php?to=admin-performance',
|
||||
forwardedForHeadersWorking: true,
|
||||
isCorrectMemcachedPHPModuleInstalled: true,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -109,6 +110,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
memcacheDocs: 'https://doc.owncloud.org/server/go.php?to=admin-performance',
|
||||
forwardedForHeadersWorking: true,
|
||||
isCorrectMemcachedPHPModuleInstalled: true,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -145,6 +147,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
isMemcacheConfigured: true,
|
||||
forwardedForHeadersWorking: true,
|
||||
isCorrectMemcachedPHPModuleInstalled: true,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -178,6 +181,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
isMemcacheConfigured: true,
|
||||
forwardedForHeadersWorking: true,
|
||||
isCorrectMemcachedPHPModuleInstalled: true,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -206,6 +210,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
isMemcacheConfigured: true,
|
||||
forwardedForHeadersWorking: true,
|
||||
isCorrectMemcachedPHPModuleInstalled: false,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -234,6 +239,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
forwardedForHeadersWorking: false,
|
||||
reverseProxyDocs: 'https://docs.owncloud.org/foo/bar.html',
|
||||
isCorrectMemcachedPHPModuleInstalled: true,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -283,6 +289,7 @@ describe('OC.SetupChecks tests', function() {
|
|||
forwardedForHeadersWorking: true,
|
||||
phpSupported: {eol: true, version: '5.4.0'},
|
||||
isCorrectMemcachedPHPModuleInstalled: true,
|
||||
hasPassedCodeIntegrityCheck: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
@ -32,6 +32,14 @@ $application->add(new OC\Core\Command\Check(\OC::$server->getConfig()));
|
|||
$infoParser = new \OC\App\InfoParser(\OC::$server->getHTTPHelper(), \OC::$server->getURLGenerator());
|
||||
$application->add(new OC\Core\Command\App\CheckCode($infoParser));
|
||||
$application->add(new OC\Core\Command\L10n\CreateJs());
|
||||
$application->add(new \OC\Core\Command\Integrity\SignApp(
|
||||
\OC::$server->getIntegrityCodeChecker(),
|
||||
new \OC\IntegrityCheck\Helpers\FileAccessHelper()
|
||||
));
|
||||
$application->add(new \OC\Core\Command\Integrity\SignCore(
|
||||
\OC::$server->getIntegrityCodeChecker(),
|
||||
new \OC\IntegrityCheck\Helpers\FileAccessHelper()
|
||||
));
|
||||
|
||||
if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
|
||||
$application->add(new OC\Core\Command\App\Disable());
|
||||
|
|
449
lib/private/integritycheck/checker.php
Normal file
449
lib/private/integritycheck/checker.php
Normal file
|
@ -0,0 +1,449 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\IntegrityCheck;
|
||||
|
||||
use OC\IntegrityCheck\Exceptions\InvalidSignatureException;
|
||||
use OC\IntegrityCheck\Helpers\AppLocator;
|
||||
use OC\IntegrityCheck\Helpers\EnvironmentHelper;
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use OC\Integritycheck\Iterator\ExcludeFileByNameFilterIterator;
|
||||
use OC\IntegrityCheck\Iterator\ExcludeFoldersByPathFilterIterator;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\ICache;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\IConfig;
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\File\X509;
|
||||
|
||||
/**
|
||||
* Class Checker handles the code signing using X.509 and RSA. ownCloud ships with
|
||||
* a public root certificate certificate that allows to issue new certificates that
|
||||
* will be trusted for signing code. The CN will be used to verify that a certificate
|
||||
* given to a third-party developer may not be used for other applications. For
|
||||
* example the author of the application "calendar" would only receive a certificate
|
||||
* only valid for this application.
|
||||
*
|
||||
* @package OC\IntegrityCheck
|
||||
*/
|
||||
class Checker {
|
||||
const CACHE_KEY = 'oc.integritycheck.checker';
|
||||
/** @var EnvironmentHelper */
|
||||
private $environmentHelper;
|
||||
/** @var AppLocator */
|
||||
private $appLocator;
|
||||
/** @var FileAccessHelper */
|
||||
private $fileAccessHelper;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
/** @var ICache */
|
||||
private $cache;
|
||||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
|
||||
/**
|
||||
* @param EnvironmentHelper $environmentHelper
|
||||
* @param FileAccessHelper $fileAccessHelper
|
||||
* @param AppLocator $appLocator
|
||||
* @param IConfig $config
|
||||
* @param ICacheFactory $cacheFactory
|
||||
* @param IAppManager $appManager
|
||||
*/
|
||||
public function __construct(EnvironmentHelper $environmentHelper,
|
||||
FileAccessHelper $fileAccessHelper,
|
||||
AppLocator $appLocator,
|
||||
IConfig $config = null,
|
||||
ICacheFactory $cacheFactory,
|
||||
IAppManager $appManager = null) {
|
||||
$this->environmentHelper = $environmentHelper;
|
||||
$this->fileAccessHelper = $fileAccessHelper;
|
||||
$this->appLocator = $appLocator;
|
||||
$this->config = $config;
|
||||
$this->cache = $cacheFactory->create(self::CACHE_KEY);
|
||||
$this->appManager = $appManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerates all files belonging to the folder. Sensible defaults are excluded.
|
||||
*
|
||||
* @param string $folderToIterate
|
||||
* @return \RecursiveIteratorIterator
|
||||
*/
|
||||
private function getFolderIterator($folderToIterate) {
|
||||
$dirItr = new \RecursiveDirectoryIterator(
|
||||
$folderToIterate,
|
||||
\RecursiveDirectoryIterator::SKIP_DOTS
|
||||
);
|
||||
$excludeGenericFilesIterator = new ExcludeFileByNameFilterIterator($dirItr);
|
||||
$excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator);
|
||||
|
||||
return new \RecursiveIteratorIterator(
|
||||
$excludeFoldersIterator,
|
||||
\RecursiveIteratorIterator::SELF_FIRST
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of ['filename' => 'SHA512-hash-of-file'] for all files found
|
||||
* in the iterator.
|
||||
*
|
||||
* @param \RecursiveIteratorIterator $iterator
|
||||
* @param string $path
|
||||
* @return array Array of hashes.
|
||||
*/
|
||||
private function generateHashes(\RecursiveIteratorIterator $iterator,
|
||||
$path) {
|
||||
$hashes = [];
|
||||
|
||||
$baseDirectoryLength = strlen($path);
|
||||
foreach($iterator as $filename => $data) {
|
||||
/** @var \DirectoryIterator $data */
|
||||
if($data->isDir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$relativeFileName = substr($filename, $baseDirectoryLength);
|
||||
|
||||
// Exclude signature.json files in the appinfo and root folder
|
||||
if($relativeFileName === '/appinfo/signature.json') {
|
||||
continue;
|
||||
}
|
||||
// Exclude signature.json files in the appinfo and core folder
|
||||
if($relativeFileName === '/core/signature.json') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hashes[$relativeFileName] = hash_file('sha512', $filename);
|
||||
}
|
||||
return $hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the signature data
|
||||
*
|
||||
* @param array $hashes
|
||||
* @param X509 $certificate
|
||||
* @param RSA $privateKey
|
||||
* @return string
|
||||
*/
|
||||
private function createSignatureData(array $hashes,
|
||||
X509 $certificate,
|
||||
RSA $privateKey) {
|
||||
ksort($hashes);
|
||||
|
||||
$privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
|
||||
$privateKey->setMGFHash('sha512');
|
||||
$signature = $privateKey->sign(json_encode($hashes));
|
||||
|
||||
return [
|
||||
'hashes' => $hashes,
|
||||
'signature' => base64_encode($signature),
|
||||
'certificate' => $certificate->saveX509($certificate->currentCert),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the signature of the specified app
|
||||
*
|
||||
* @param string $appId
|
||||
* @param X509 $certificate
|
||||
* @param RSA $privateKey
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function writeAppSignature($appId,
|
||||
X509 $certificate,
|
||||
RSA $privateKey) {
|
||||
$path = $this->appLocator->getAppPath($appId);
|
||||
$iterator = $this->getFolderIterator($path);
|
||||
$hashes = $this->generateHashes($iterator, $path);
|
||||
$signature = $this->createSignatureData($hashes, $certificate, $privateKey);
|
||||
$this->fileAccessHelper->file_put_contents(
|
||||
$path . '/appinfo/signature.json',
|
||||
json_encode($signature, JSON_PRETTY_PRINT)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the signature of core
|
||||
*
|
||||
* @param X509 $certificate
|
||||
* @param RSA $rsa
|
||||
*/
|
||||
public function writeCoreSignature(X509 $certificate,
|
||||
RSA $rsa) {
|
||||
$iterator = $this->getFolderIterator($this->environmentHelper->getServerRoot());
|
||||
$hashes = $this->generateHashes($iterator, $this->environmentHelper->getServerRoot());
|
||||
$signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
|
||||
$this->fileAccessHelper->file_put_contents(
|
||||
$this->environmentHelper->getServerRoot() . '/core/signature.json',
|
||||
json_encode($signatureData, JSON_PRETTY_PRINT)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the signature for the specified path.
|
||||
*
|
||||
* @param string $signaturePath
|
||||
* @param string $basePath
|
||||
* @param string $certificateCN
|
||||
* @return array
|
||||
* @throws InvalidSignatureException
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function verify($signaturePath, $basePath, $certificateCN) {
|
||||
$signatureData = json_decode($this->fileAccessHelper->file_get_contents($signaturePath), true);
|
||||
if(!is_array($signatureData)) {
|
||||
throw new InvalidSignatureException('Signature data not found.');
|
||||
}
|
||||
|
||||
$expectedHashes = $signatureData['hashes'];
|
||||
ksort($expectedHashes);
|
||||
$signature = base64_decode($signatureData['signature']);
|
||||
$certificate = $signatureData['certificate'];
|
||||
|
||||
// Check if certificate is signed by ownCloud Root Authority
|
||||
$x509 = new \phpseclib\File\X509();
|
||||
$rootCertificatePublicKey = $this->fileAccessHelper->file_get_contents($this->environmentHelper->getServerRoot().'/resources/codesigning/root.crt');
|
||||
$x509->loadCA($rootCertificatePublicKey);
|
||||
$x509->loadX509($certificate);
|
||||
if(!$x509->validateSignature()) {
|
||||
throw new InvalidSignatureException('Certificate is not valid.');
|
||||
}
|
||||
// Verify if certificate has proper CN. "core" CN is always trusted.
|
||||
if($x509->getDN(X509::DN_OPENSSL)['CN'] !== $certificateCN && $x509->getDN(X509::DN_OPENSSL)['CN'] !== 'core') {
|
||||
throw new InvalidSignatureException(
|
||||
sprintf('Certificate is not valid for required scope. (Requested: %s, current: %s)', $certificateCN, $x509->getDN(true))
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the signature of the files is valid
|
||||
$rsa = new \phpseclib\Crypt\RSA();
|
||||
$rsa->loadKey($x509->currentCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']);
|
||||
$rsa->setSignatureMode(RSA::SIGNATURE_PSS);
|
||||
$rsa->setMGFHash('sha512');
|
||||
if(!$rsa->verify(json_encode($expectedHashes), $signature)) {
|
||||
throw new InvalidSignatureException('Signature could not get verified.');
|
||||
}
|
||||
|
||||
// Compare the list of files which are not identical
|
||||
$currentInstanceHashes = $this->generateHashes($this->getFolderIterator($basePath), $basePath);
|
||||
$differencesA = array_diff($expectedHashes, $currentInstanceHashes);
|
||||
$differencesB = array_diff($currentInstanceHashes, $expectedHashes);
|
||||
$differences = array_unique(array_merge($differencesA, $differencesB));
|
||||
$differenceArray = [];
|
||||
foreach($differences as $filename => $hash) {
|
||||
// Check if file should not exist in the new signature table
|
||||
if(!array_key_exists($filename, $expectedHashes)) {
|
||||
$differenceArray['EXTRA_FILE'][$filename]['expected'] = '';
|
||||
$differenceArray['EXTRA_FILE'][$filename]['current'] = $hash;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if file is missing
|
||||
if(!array_key_exists($filename, $currentInstanceHashes)) {
|
||||
$differenceArray['FILE_MISSING'][$filename]['expected'] = $expectedHashes[$filename];
|
||||
$differenceArray['FILE_MISSING'][$filename]['current'] = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if hash does mismatch
|
||||
if($expectedHashes[$filename] !== $currentInstanceHashes[$filename]) {
|
||||
$differenceArray['INVALID_HASH'][$filename]['expected'] = $expectedHashes[$filename];
|
||||
$differenceArray['INVALID_HASH'][$filename]['current'] = $currentInstanceHashes[$filename];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Should never happen.
|
||||
throw new \Exception('Invalid behaviour in file hash comparison experienced. Please report this error to the developers.');
|
||||
}
|
||||
|
||||
return $differenceArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the code integrity check has passed successful or not
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPassedCheck() {
|
||||
$results = $this->getResults();
|
||||
if(empty($results)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResults() {
|
||||
$cachedResults = $this->cache->get(self::CACHE_KEY);
|
||||
if(!is_null($cachedResults)) {
|
||||
return json_decode($cachedResults, true);
|
||||
}
|
||||
|
||||
return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the results in the app config as well as cache
|
||||
*
|
||||
* @param string $scope
|
||||
* @param array $result
|
||||
*/
|
||||
private function storeResults($scope, array $result) {
|
||||
$resultArray = $this->getResults();
|
||||
unset($resultArray[$scope]);
|
||||
if(!empty($result)) {
|
||||
$resultArray[$scope] = $result;
|
||||
}
|
||||
$this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
|
||||
$this->cache->set(self::CACHE_KEY, json_encode($resultArray));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verify the signature of $appId. Returns an array with the following content:
|
||||
* [
|
||||
* 'FILE_MISSING' =>
|
||||
* [
|
||||
* 'filename' => [
|
||||
* 'expected' => 'expectedSHA512',
|
||||
* 'current' => 'currentSHA512',
|
||||
* ],
|
||||
* ],
|
||||
* 'EXTRA_FILE' =>
|
||||
* [
|
||||
* 'filename' => [
|
||||
* 'expected' => 'expectedSHA512',
|
||||
* 'current' => 'currentSHA512',
|
||||
* ],
|
||||
* ],
|
||||
* 'INVALID_HASH' =>
|
||||
* [
|
||||
* 'filename' => [
|
||||
* 'expected' => 'expectedSHA512',
|
||||
* 'current' => 'currentSHA512',
|
||||
* ],
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* Array may be empty in case no problems have been found.
|
||||
*
|
||||
* @param string $appId
|
||||
* @return array
|
||||
*/
|
||||
public function verifyAppSignature($appId) {
|
||||
try {
|
||||
$path = $this->appLocator->getAppPath($appId);
|
||||
$result = $this->verify(
|
||||
$path . '/appinfo/signature.json',
|
||||
$path,
|
||||
$appId
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$result = [
|
||||
'EXCEPTION' => [
|
||||
'class' => get_class($e),
|
||||
'message' => $e->getMessage(),
|
||||
],
|
||||
];
|
||||
}
|
||||
$this->storeResults($appId, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the signature of core. Returns an array with the following content:
|
||||
* [
|
||||
* 'FILE_MISSING' =>
|
||||
* [
|
||||
* 'filename' => [
|
||||
* 'expected' => 'expectedSHA512',
|
||||
* 'current' => 'currentSHA512',
|
||||
* ],
|
||||
* ],
|
||||
* 'EXTRA_FILE' =>
|
||||
* [
|
||||
* 'filename' => [
|
||||
* 'expected' => 'expectedSHA512',
|
||||
* 'current' => 'currentSHA512',
|
||||
* ],
|
||||
* ],
|
||||
* 'INVALID_HASH' =>
|
||||
* [
|
||||
* 'filename' => [
|
||||
* 'expected' => 'expectedSHA512',
|
||||
* 'current' => 'currentSHA512',
|
||||
* ],
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* Array may be empty in case no problems have been found.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function verifyCoreSignature() {
|
||||
try {
|
||||
$result = $this->verify(
|
||||
$this->environmentHelper->getServerRoot() . '/core/signature.json',
|
||||
$this->environmentHelper->getServerRoot(),
|
||||
'core'
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$result = [
|
||||
'EXCEPTION' => [
|
||||
'class' => get_class($e),
|
||||
'message' => $e->getMessage(),
|
||||
],
|
||||
];
|
||||
}
|
||||
$this->storeResults('core', $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the core code of the instance as well as all applicable applications
|
||||
* and store the results.
|
||||
*/
|
||||
public function runInstanceVerification() {
|
||||
$this->verifyCoreSignature();
|
||||
$appIds = $this->appLocator->getAllApps();
|
||||
foreach($appIds as $appId) {
|
||||
// If an application is shipped a valid signature is required
|
||||
$isShipped = $this->appManager->isShipped($appId);
|
||||
$appNeedsToBeChecked = false;
|
||||
if ($isShipped) {
|
||||
$appNeedsToBeChecked = true;
|
||||
} elseif ($this->fileAccessHelper->file_exists($this->appLocator->getAppPath($appId) . '/appinfo/signature.json')) {
|
||||
// Otherwise only if the application explicitly ships a signature.json file
|
||||
$appNeedsToBeChecked = true;
|
||||
}
|
||||
|
||||
if($appNeedsToBeChecked) {
|
||||
$this->verifyAppSignature($appId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\IntegrityCheck\Exceptions;
|
||||
|
||||
/**
|
||||
* Class InvalidSignatureException is thrown in case the signature of the hashes
|
||||
* cannot be properly validated. This indicates that either files
|
||||
*
|
||||
* @package OC\IntegrityCheck\Exceptions
|
||||
*/
|
||||
class InvalidSignatureException extends \Exception {}
|
56
lib/private/integritycheck/helpers/applocator.php
Normal file
56
lib/private/integritycheck/helpers/applocator.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\IntegrityCheck\Helpers;
|
||||
|
||||
/**
|
||||
* Class AppLocator provides a non-static helper for OC_App::getPath($appId)
|
||||
* it is not possible to use IAppManager at this point as IAppManager has a
|
||||
* dependency on a running ownCloud.
|
||||
*
|
||||
* @package OC\IntegrityCheck\Helpers
|
||||
*/
|
||||
class AppLocator {
|
||||
/**
|
||||
* Provides \OC_App::getAppPath($appId)
|
||||
*
|
||||
* @param string $appId
|
||||
* @return string
|
||||
* @throws \Exception If the app cannot be found
|
||||
*/
|
||||
public function getAppPath($appId) {
|
||||
$path = \OC_App::getAppPath($appId);
|
||||
if($path === false) {
|
||||
|
||||
throw new \Exception('App not found');
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Providers \OC_App::getAllApps()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAllApps() {
|
||||
return \OC_App::getAllApps();
|
||||
}
|
||||
}
|
39
lib/private/integritycheck/helpers/environmenthelper.php
Normal file
39
lib/private/integritycheck/helpers/environmenthelper.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\IntegrityCheck\Helpers;
|
||||
|
||||
/**
|
||||
* Class EnvironmentHelper provides a non-static helper for access to static
|
||||
* variables such as \OC::$SERVERROOT.
|
||||
*
|
||||
* @package OC\IntegrityCheck\Helpers
|
||||
*/
|
||||
class EnvironmentHelper {
|
||||
/**
|
||||
* Provides \OC::$SERVERROOT
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getServerRoot() {
|
||||
return \OC::$SERVERROOT;
|
||||
}
|
||||
}
|
61
lib/private/integritycheck/helpers/fileaccesshelper.php
Normal file
61
lib/private/integritycheck/helpers/fileaccesshelper.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\IntegrityCheck\Helpers;
|
||||
|
||||
/**
|
||||
* Class FileAccessHelper provides a helper around file_get_contents and
|
||||
* file_put_contents
|
||||
*
|
||||
* @package OC\IntegrityCheck\Helpers
|
||||
*/
|
||||
class FileAccessHelper {
|
||||
/**
|
||||
* Wrapper around file_get_contents($filename, $data)
|
||||
*
|
||||
* @param string $filename
|
||||
* @return string|false
|
||||
*/
|
||||
public function file_get_contents($filename) {
|
||||
return file_get_contents($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around file_exists($filename)
|
||||
*
|
||||
* @param string $filename
|
||||
* @return bool
|
||||
*/
|
||||
public function file_exists($filename) {
|
||||
return file_exists($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around file_put_contents($filename, $data)
|
||||
*
|
||||
* @param string $filename
|
||||
* @param $data
|
||||
* @return int|false
|
||||
*/
|
||||
public function file_put_contents($filename, $data) {
|
||||
return file_put_contents($filename, $data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\IntegrityCheck\Iterator;
|
||||
|
||||
/**
|
||||
* Class ExcludeFileByNameFilterIterator provides a custom iterator which excludes
|
||||
* entries with the specified file name from the file list.
|
||||
*
|
||||
* @package OC\Integritycheck\Iterator
|
||||
*/
|
||||
class ExcludeFileByNameFilterIterator extends \RecursiveFilterIterator {
|
||||
/**
|
||||
* Array of excluded file names. Those are not scanned by the integrity checker.
|
||||
* This is used to exclude files which administrators could upload by mistakes
|
||||
* such as .DS_Store files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $excludedFilenames = [
|
||||
'.DS_Store', // Mac OS X
|
||||
'Thumbs.db', // Microsoft Windows
|
||||
'.directory', // Dolphin (KDE)
|
||||
];
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function accept() {
|
||||
if($this->isDir()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !in_array(
|
||||
$this->current()->getFilename(),
|
||||
$this->excludedFilenames,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\IntegrityCheck\Iterator;
|
||||
|
||||
class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator {
|
||||
private $excludedFolders = [];
|
||||
|
||||
public function __construct(\RecursiveIterator $iterator) {
|
||||
parent::__construct($iterator);
|
||||
|
||||
$appFolders = \OC::$APPSROOTS;
|
||||
foreach($appFolders as $key => $appFolder) {
|
||||
$appFolders[$key] = rtrim($appFolder['path'], '/');
|
||||
}
|
||||
|
||||
$this->excludedFolders = array_merge([
|
||||
rtrim(\OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data'), '/'),
|
||||
rtrim(\OC::$SERVERROOT.'/themes', '/'),
|
||||
], $appFolders);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function accept() {
|
||||
return !in_array(
|
||||
$this->current()->getPathName(),
|
||||
$this->excludedFolders,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
|
@ -51,6 +51,10 @@ use OC\Files\Node\HookConnector;
|
|||
use OC\Files\Node\Root;
|
||||
use OC\Files\View;
|
||||
use OC\Http\Client\ClientService;
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OC\IntegrityCheck\Helpers\AppLocator;
|
||||
use OC\IntegrityCheck\Helpers\EnvironmentHelper;
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use OC\Lock\DBLockingProvider;
|
||||
use OC\Lock\MemcacheLockingProvider;
|
||||
use OC\Lock\NoopLockingProvider;
|
||||
|
@ -409,6 +413,26 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
$this->registerService('TrustedDomainHelper', function ($c) {
|
||||
return new TrustedDomainHelper($this->getConfig());
|
||||
});
|
||||
$this->registerService('IntegrityCodeChecker', function (Server $c) {
|
||||
// IConfig and IAppManager requires a working database. This code
|
||||
// might however be called when ownCloud is not yet setup.
|
||||
if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
|
||||
$config = $c->getConfig();
|
||||
$appManager = $c->getAppManager();
|
||||
} else {
|
||||
$config = null;
|
||||
$appManager = null;
|
||||
}
|
||||
|
||||
return new Checker(
|
||||
new EnvironmentHelper(),
|
||||
new FileAccessHelper(),
|
||||
new AppLocator(),
|
||||
$config,
|
||||
$c->getMemCacheFactory(),
|
||||
$appManager
|
||||
);
|
||||
});
|
||||
$this->registerService('Request', function ($c) {
|
||||
if (isset($this['urlParams'])) {
|
||||
$urlParams = $this['urlParams'];
|
||||
|
@ -1093,6 +1117,13 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
return $this->query('NotificationManager');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OC\IntegrityCheck\Checker
|
||||
*/
|
||||
public function getIntegrityCodeChecker() {
|
||||
return $this->query('IntegrityCodeChecker');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OC\Session\CryptoWrapper
|
||||
*/
|
||||
|
|
|
@ -78,8 +78,12 @@ class OC_TemplateLayout extends OC_Template {
|
|||
// Update notification
|
||||
if($this->config->getSystemValue('updatechecker', true) === true &&
|
||||
OC_User::isAdminUser(OC_User::getUser())) {
|
||||
$updater = new \OC\Updater(\OC::$server->getHTTPHelper(),
|
||||
\OC::$server->getConfig(), \OC::$server->getLogger());
|
||||
$updater = new \OC\Updater(
|
||||
\OC::$server->getHTTPHelper(),
|
||||
\OC::$server->getConfig(),
|
||||
\OC::$server->getIntegrityCodeChecker(),
|
||||
\OC::$server->getLogger()
|
||||
);
|
||||
$data = $updater->check();
|
||||
|
||||
if(isset($data['version']) && $data['version'] != '' and $data['version'] !== Array()) {
|
||||
|
@ -96,8 +100,13 @@ class OC_TemplateLayout extends OC_Template {
|
|||
$this->assign('updateAvailable', false); // Update check is disabled
|
||||
}
|
||||
|
||||
// Add navigation entry
|
||||
// Code integrity notification
|
||||
$integrityChecker = \OC::$server->getIntegrityCodeChecker();
|
||||
if(!$integrityChecker->hasPassedCheck()) {
|
||||
\OCP\Util::addScript('core', 'integritycheck-failed-notification');
|
||||
}
|
||||
|
||||
// Add navigation entry
|
||||
$this->assign( 'application', '');
|
||||
$this->assign( 'appid', $appId );
|
||||
$navigation = OC_App::getNavigation();
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
namespace OC;
|
||||
|
||||
use OC\Hooks\BasicEmitter;
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OC\IntegrityCheck\Storage;
|
||||
use OC_App;
|
||||
use OC_Installer;
|
||||
use OC_Util;
|
||||
|
@ -61,6 +63,9 @@ class Updater extends BasicEmitter {
|
|||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
|
||||
/** @var bool */
|
||||
private $simulateStepEnabled;
|
||||
|
||||
|
@ -81,14 +86,17 @@ class Updater extends BasicEmitter {
|
|||
/**
|
||||
* @param HTTPHelper $httpHelper
|
||||
* @param IConfig $config
|
||||
* @param Checker $checker
|
||||
* @param ILogger $log
|
||||
*/
|
||||
public function __construct(HTTPHelper $httpHelper,
|
||||
IConfig $config,
|
||||
Checker $checker,
|
||||
ILogger $log = null) {
|
||||
$this->httpHelper = $httpHelper;
|
||||
$this->log = $log;
|
||||
$this->config = $config;
|
||||
$this->checker = $checker;
|
||||
$this->simulateStepEnabled = true;
|
||||
$this->updateStepEnabled = true;
|
||||
}
|
||||
|
@ -335,6 +343,13 @@ class Updater extends BasicEmitter {
|
|||
//Invalidate update feed
|
||||
$this->config->setAppValue('core', 'lastupdatedat', 0);
|
||||
|
||||
// Check for code integrity on the stable channel
|
||||
if(\OC_Util::getChannel() === 'stable') {
|
||||
$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
|
||||
$this->checker->runInstanceVerification();
|
||||
$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
|
||||
}
|
||||
|
||||
// only set the final version if everything went well
|
||||
$this->config->setSystemValue('version', implode('.', \OC_Util::getVersion()));
|
||||
}
|
||||
|
|
28
resources/codesigning/core.crt
Normal file
28
resources/codesigning/core.crt
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEvjCCAqagAwIBAgIUc/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF
|
||||
BQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw
|
||||
MzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ
|
||||
KoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s
|
||||
iOf4RwPXR6SE9bWZEm/b72SfWk//J6AbrD8WiOzBuT/ODy6k5T1arEdHO+Pux0W1
|
||||
MxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr/xolP3oD+eLbShPcblhdS
|
||||
VtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0
|
||||
klnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5/2riAzIssMFSCarWCx0AKYb54+d
|
||||
xLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77
|
||||
H87KFhYW8tKFFvF1V3AHl/sFQ9tDHaxM9Y0pZ2jPp/ccdiqnmdkBxBDqsiRvHvVB
|
||||
Cn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO/wAtd2vUW8UFiq
|
||||
s2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ/zrM0
|
||||
i8nfCFwTxWRxp3H9KoECzO/zS5R5KIS7s3/wq/w9T2Ie4rcecgXwDizwnn0C/aKc
|
||||
bDIjujpL1s9HO05pcD/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ
|
||||
Q238lC+A/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2
|
||||
AvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji
|
||||
oNCXUbExC/0iCPUqdHZIVb+Lc/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd
|
||||
9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb
|
||||
H+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th/55
|
||||
cf3Fovj6JJgbb9XFxrdnsOsDOu/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX
|
||||
uVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO//+TJtXRbyNgsf
|
||||
oMRZGi8DLGU2SGEAHcRH/QZHq/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1
|
||||
0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI/XUxEWOa2F
|
||||
K2EqhErgMK/N07U1JJJay5tYZRtvkGq46oP/5kQG8hYST0MDK6VihJoPpvCmAm4E
|
||||
pEYKQ96x6A4EH9Y9mZlYozH/eqmxPbTK8n89/p7Ydun4rI+B2iiLnY8REWWy6+UQ
|
||||
V204fGUkJqW5CrKy3P3XvY9X
|
||||
-----END CERTIFICATE-----
|
51
resources/codesigning/core.key
Normal file
51
resources/codesigning/core.key
Normal file
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
28
resources/codesigning/root.crt
Normal file
28
resources/codesigning/root.crt
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIE1DCCArygAwIBAgIUFgEnT7tUWNgEKfbMiRTOm3Z8figwDQYJKoZIhvcNAQEF
|
||||
BQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMCAXDTE1MTEw
|
||||
MzIxMDMzMloYDzk5OTkxMjMxMjM1OTU5WjAjMSEwHwYDVQQKDBhvd25DbG91ZCBD
|
||||
b2RlIFNpZ25pbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCt
|
||||
rYEwiwpuhzRNx1L2SntkL/zalA7OkwEcsBn4Ysw47nEdvp648AVohT7d+U7+DWix
|
||||
O06xvlAJUhqYTXX7EG9n+mBnG+TIMq2zlei0Jj3uq1pEZE9elfGZael2uc8gRXMZ
|
||||
YFmSlTvzexqvfK4B3DwoZaMaWJecEO9iyuUyzHMBpE8bHtGDOUGy/oTO9WASbtl9
|
||||
Rfk38VLLV6csCPwKjii6Q3YZ+AYU0YqLg22BwZlqlTexUjWAmVIqaoxmSEuKa41X
|
||||
nuAIHfP65oiob86s4IvJXVr3r7NjdF2IJ/ZrwmjGKaWgSZKcoZBPLArZJeJiIQ4Y
|
||||
KzLZATwba5dWswV0mbDj8eP2BG+02NVKxylOBbeoBESnahZeZ5nJ5XKZr+ErJAUW
|
||||
b417fEnYaQNBlNnijjkqXaDipmTktUfnv4lm30sUAgho6I3Ga7gQrFPzKg9V4j2S
|
||||
+LOTc1HmJOnR6Kfttx+yAHYLKtvV5yIMMpz+rZ2X5g/N2GdgleZj5VU9nmKzTPeG
|
||||
x6V+dBaIkqNe8/AXaVnxt9KSb03Q/+CFjKTNDtEN5fNJuXS0+h+oop6nhpktM2i7
|
||||
gCpxeLNEaQaeoxR5093VN00oOJOYBvQoVGEDftEwdG6dWbTZsIykBF7aK+p8DMy9
|
||||
tCdc2GnGMEuFlUNA9ucv2Rv7IcuPdspnK31CZoMNKwIDAQABMA0GCSqGSIb3DQEB
|
||||
BQUAA4ICAQBROWec0HOsnLPN40gkBQ62mNBUJgcAr5K2eMIEMSRFRD2ldEVOvmCO
|
||||
u1Q62umy9tiSRiFQTcG1J9k0zlOjy/hfpBl2G1Zce0OoEeuNkH7c0W/idHSloWRZ
|
||||
YlK3tVJD6DzY6s9VbO6e/ncecNsXkirkWp/cvMYquH2d4OmSl0/hW0VMdxOCLxkA
|
||||
xbW+3Dh05u7tgKVRD67/GRvLtg+xHaOJqiOh3MpMaHy+6xT5Fd5K2QC0pcGtZuqF
|
||||
EnnfdeUI/Dy76yQE8pBfjaUFf3TS1n1E6kun1Nkf0X4pvwi8W1goLsPu5sWDNNga
|
||||
1RGYj0o5OdIo27qebfmu76WX0fNNd47VabtzNV+W7Msj0yeZg+hxAtAvs0ZEyJh+
|
||||
4biWsv+ALSlqz4sSdoOVGUEBdnkUrWN19lou62ix9vTmuCrVEA3TuZA3PR0+hqqQ
|
||||
/A/DcmWwxWYKyaBgxwHc/nGo1qWrDh22P5Rp7++Zw3kOCY6QmeJkAiHFs6Crw4ub
|
||||
HKVMw3fV5H9oiUFjadPZoCU51uXKX4YRqKxWJ5djlp4r1GCEQHyxngTsmH3komnw
|
||||
kh4LsEQRqdhuT0A4sZN7CenMJfQiFqupL7RVSycJFQpgzwVFmOzjCVT4PT/W5ARv
|
||||
9YtqEkvyoRTwErwuN/FIVvhWnIP/C69Z1/T/nXyj86P2G7PMgnchIQ==
|
||||
-----END CERTIFICATE-----
|
51
resources/codesigning/root.key
Normal file
51
resources/codesigning/root.key
Normal file
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -40,6 +40,7 @@ use OC\Settings\Middleware\SubadminMiddleware;
|
|||
use \OCP\AppFramework\App;
|
||||
use OCP\IContainer;
|
||||
use \OCP\Util;
|
||||
use OC\Server;
|
||||
|
||||
/**
|
||||
* @package OC\Settings
|
||||
|
@ -154,7 +155,8 @@ class Application extends App {
|
|||
$c->query('ClientService'),
|
||||
$c->query('URLGenerator'),
|
||||
$c->query('Util'),
|
||||
$c->query('L10N')
|
||||
$c->query('L10N'),
|
||||
$c->query('Checker')
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -240,5 +242,10 @@ class Application extends App {
|
|||
$container->registerService('CertificateManager', function(IContainer $c){
|
||||
return $c->query('ServerContainer')->getCertificateManager();
|
||||
});
|
||||
$container->registerService('Checker', function(IContainer $c) {
|
||||
/** @var Server $server */
|
||||
$server = $c->query('ServerContainer');
|
||||
return $server->getIntegrityCodeChecker();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,12 @@
|
|||
namespace OC\Settings\Controller;
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use OC\AppFramework\Http;
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\DataDisplayResponse;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\Http\Client\IClientService;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
|
@ -49,6 +53,8 @@ class CheckSetupController extends Controller {
|
|||
private $urlGenerator;
|
||||
/** @var IL10N */
|
||||
private $l10n;
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
|
||||
/**
|
||||
* @param string $AppName
|
||||
|
@ -58,6 +64,7 @@ class CheckSetupController extends Controller {
|
|||
* @param IURLGenerator $urlGenerator
|
||||
* @param \OC_Util $util
|
||||
* @param IL10N $l10n
|
||||
* @param Checker $checker
|
||||
*/
|
||||
public function __construct($AppName,
|
||||
IRequest $request,
|
||||
|
@ -65,13 +72,15 @@ class CheckSetupController extends Controller {
|
|||
IClientService $clientService,
|
||||
IURLGenerator $urlGenerator,
|
||||
\OC_Util $util,
|
||||
IL10N $l10n) {
|
||||
IL10N $l10n,
|
||||
Checker $checker) {
|
||||
parent::__construct($AppName, $request);
|
||||
$this->config = $config;
|
||||
$this->clientService = $clientService;
|
||||
$this->util = $util;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->l10n = $l10n;
|
||||
$this->checker = $checker;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,6 +256,72 @@ class CheckSetupController extends Controller {
|
|||
return !(!extension_loaded('memcached') && extension_loaded('memcache'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function rescanFailedIntegrityCheck() {
|
||||
$this->checker->runInstanceVerification();
|
||||
return new RedirectResponse(
|
||||
$this->urlGenerator->linkToRoute('settings_admin')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function getFailedIntegrityCheckFiles() {
|
||||
$completeResults = $this->checker->getResults();
|
||||
|
||||
if(!empty($completeResults)) {
|
||||
$formattedTextResponse = 'Technical information
|
||||
=====================
|
||||
The following list covers which files have failed the integrity check. Please read
|
||||
the previous linked documentation to learn more about the errors and how to fix
|
||||
them.
|
||||
|
||||
Results
|
||||
=======
|
||||
';
|
||||
foreach($completeResults as $context => $contextResult) {
|
||||
$formattedTextResponse .= "- $context\n";
|
||||
|
||||
foreach($contextResult as $category => $result) {
|
||||
$formattedTextResponse .= "\t- $category\n";
|
||||
if($category !== 'EXCEPTION') {
|
||||
foreach ($result as $key => $results) {
|
||||
$formattedTextResponse .= "\t\t- $key\n";
|
||||
}
|
||||
} else {
|
||||
foreach ($result as $key => $results) {
|
||||
$formattedTextResponse .= "\t\t- $results\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$formattedTextResponse .= '
|
||||
Raw output
|
||||
==========
|
||||
';
|
||||
$formattedTextResponse .= print_r($completeResults, true);
|
||||
} else {
|
||||
$formattedTextResponse = 'No errors have been found.';
|
||||
}
|
||||
|
||||
|
||||
$response = new DataDisplayResponse(
|
||||
$formattedTextResponse,
|
||||
Http::STATUS_OK,
|
||||
[
|
||||
'Content-Type' => 'text/plain',
|
||||
]
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DataResponse
|
||||
*/
|
||||
|
@ -263,7 +338,9 @@ class CheckSetupController extends Controller {
|
|||
'phpSupported' => $this->isPhpSupported(),
|
||||
'forwardedForHeadersWorking' => $this->forwardedForHeadersWorking(),
|
||||
'reverseProxyDocs' => $this->urlGenerator->linkToDocs('admin-reverse-proxy'),
|
||||
'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled()
|
||||
'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled(),
|
||||
'hasPassedCodeIntegrityCheck' => $this->checker->hasPassedCheck(),
|
||||
'codeIntegrityCheckerDocumentation' => $this->urlGenerator->linkToDocs('admin-code-integrity'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ $application->registerRoutes($this, [
|
|||
['name' => 'LogSettings#getEntries', 'url' => '/settings/admin/log/entries', 'verb' => 'GET'],
|
||||
['name' => 'LogSettings#download', 'url' => '/settings/admin/log/download', 'verb' => 'GET'],
|
||||
['name' => 'CheckSetup#check', 'url' => '/settings/ajax/checksetup', 'verb' => 'GET'],
|
||||
['name' => 'CheckSetup#getFailedIntegrityCheckFiles', 'url' => '/settings/integrity/failed', 'verb' => 'GET'],
|
||||
['name' => 'CheckSetup#rescanFailedIntegrityCheck', 'url' => '/settings/integrity/rescan', 'verb' => 'GET'],
|
||||
['name' => 'Certificate#addPersonalRootCertificate', 'url' => '/settings/personal/certificate', 'verb' => 'POST'],
|
||||
['name' => 'Certificate#removePersonalRootCertificate', 'url' => '/settings/personal/certificate/{certificateIdentifier}', 'verb' => 'DELETE'],
|
||||
]
|
||||
|
|
28
tests/data/integritycheck/SomeApp.crt
Normal file
28
tests/data/integritycheck/SomeApp.crt
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEwTCCAqmgAwIBAgIUWv0iujufs5lUr0svCf/qTQvoyKAwDQYJKoZIhvcNAQEF
|
||||
BQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw
|
||||
MzIyNDk1M1oXDTE2MTEwMzIyNDk1M1owEjEQMA4GA1UEAwwHU29tZUFwcDCCAiIw
|
||||
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK8q0x62agGSRBqeWsaeEwFfepMk
|
||||
F8cAobMMi50qHCv9IrOn/ZH9l52xBrbIkErVmRjmly0d4JhD8Ymhidsh9ONKYl/j
|
||||
+ishsZDM8eNNdp3Ew+fEYVvY1W7mR1qU24NWj0bzVsClI7hvPVIuw7AjfBDq1C5+
|
||||
A+ZSLSXYvOK2cEWjdxQfuNZwEZSjmA63DUllBIrm35IaTvfuyhU6BW9yHZxmb8+M
|
||||
w0xDv30D5UkE/2N7Pa/HQJLxCR+3zKibRK3nUyRDLSXxMkU9PnFNaPNX59VPgyj4
|
||||
GB1CFSToldJVPF4pzh7p36uGXZVxs8m3LFD4Ol8mhi7jkxDZjqFN46gzR0r23Py6
|
||||
dol9vfawGIoUwp9LvL0S7MvdRY0oazLXwClLP4OQ17zpSMAiCj7fgNT661JamPGj
|
||||
t5O7Zn2wA7I4ddDS/HDTWCu98Zwc9fHIpsJPgCZ9awoqxi4Mnf7Pk9g5nnXhszGC
|
||||
cxxIASQKM+GhdzoRxKknax2RzUCwCzcPRtCj8AQT/x/mqN3PfRmlnFBNACUw9bpZ
|
||||
SOoNq2pCF9igftDWpSIXQ38pVpKLWowjjg3DVRmVKBgivHnUnVLyzYBahHPj0vaz
|
||||
tFtUFRaqXDnt+4qyUGyrT5h5pjZaTcHIcSB4PiarYwdVvgslgwnQzOUcGAzRWBD4
|
||||
6jV2brP5vFY3g6iPAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBACTY3CCHC+Z28gCf
|
||||
FWGKQ3wAKs+k4+0yoti0qm2EKX7rSGQ0PHSas6uW79WstC4Rj+DYkDtIhGMSg8FS
|
||||
HVGZHGBCc0HwdX+BOAt3zi4p7Sf3oQef70/4imPoKxbAVCpd/cveVcFyDC19j1yB
|
||||
Bapwu87oh+muoeaZxOlqQI4UxjBlR/uRSMhOn2UGauIr3dWJgAF4pGt7TtIzt+1v
|
||||
0uA6FtN1Y4R5O8AaJPh1bIG0CVvFBE58esGzjEYLhOydgKFnEP94kVPgJD5ds9C3
|
||||
pPhEpo1dRpiXaF7WGIV1X6DI/ipWvfrF7CEy6I/kP1InY/vMDjQjeDnJ/VrXIWXO
|
||||
yZvHXVaN/m+1RlETsH7YO/QmxRue9ZHN3gvvWtmpCeA95sfpepOk7UcHxHZYyQbF
|
||||
49/au8j+5tsr4A83xzsT1JbcKRxkAaQ7WDJpOnE5O1+H0fB+BaLakTg6XX9d4Fo7
|
||||
7Gin7hVWX7pL+JIyxMzME3LhfI61+CRcqZQIrpyaafUziPQbWIPfEs7h8tCOWyvW
|
||||
UO8ZLervYCB3j44ivkrxPlcBklDCqqKKBzDP9dYOtS/P4RB1NkHA9+NTvmBpTonS
|
||||
SFXdg9fFMD7VfjDE3Vnk+8DWkVH5wBYowTAD7w9Wuzr7DumiAULexnP/Y7xwxLv7
|
||||
4B+pXTAcRK0zECDEaX3npS8xWzrB
|
||||
-----END CERTIFICATE-----
|
51
tests/data/integritycheck/SomeApp.key
Normal file
51
tests/data/integritycheck/SomeApp.key
Normal file
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
1
tests/data/integritycheck/app/AnotherFile.txt
Normal file
1
tests/data/integritycheck/app/AnotherFile.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Another file with some Content.
|
1
tests/data/integritycheck/app/subfolder/file.txt
Normal file
1
tests/data/integritycheck/app/subfolder/file.txt
Normal file
|
@ -0,0 +1 @@
|
|||
A file with some content.
|
|
@ -0,0 +1 @@
|
|||
TAMPERED FILE.
|
28
tests/data/integritycheck/core.crt
Normal file
28
tests/data/integritycheck/core.crt
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEvjCCAqagAwIBAgIUc/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF
|
||||
BQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw
|
||||
MzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ
|
||||
KoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s
|
||||
iOf4RwPXR6SE9bWZEm/b72SfWk//J6AbrD8WiOzBuT/ODy6k5T1arEdHO+Pux0W1
|
||||
MxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr/xolP3oD+eLbShPcblhdS
|
||||
VtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0
|
||||
klnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5/2riAzIssMFSCarWCx0AKYb54+d
|
||||
xLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77
|
||||
H87KFhYW8tKFFvF1V3AHl/sFQ9tDHaxM9Y0pZ2jPp/ccdiqnmdkBxBDqsiRvHvVB
|
||||
Cn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO/wAtd2vUW8UFiq
|
||||
s2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ/zrM0
|
||||
i8nfCFwTxWRxp3H9KoECzO/zS5R5KIS7s3/wq/w9T2Ie4rcecgXwDizwnn0C/aKc
|
||||
bDIjujpL1s9HO05pcD/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ
|
||||
Q238lC+A/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2
|
||||
AvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji
|
||||
oNCXUbExC/0iCPUqdHZIVb+Lc/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd
|
||||
9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb
|
||||
H+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th/55
|
||||
cf3Fovj6JJgbb9XFxrdnsOsDOu/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX
|
||||
uVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO//+TJtXRbyNgsf
|
||||
oMRZGi8DLGU2SGEAHcRH/QZHq/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1
|
||||
0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI/XUxEWOa2F
|
||||
K2EqhErgMK/N07U1JJJay5tYZRtvkGq46oP/5kQG8hYST0MDK6VihJoPpvCmAm4E
|
||||
pEYKQ96x6A4EH9Y9mZlYozH/eqmxPbTK8n89/p7Ydun4rI+B2iiLnY8REWWy6+UQ
|
||||
V204fGUkJqW5CrKy3P3XvY9X
|
||||
-----END CERTIFICATE-----
|
51
tests/data/integritycheck/core.key
Normal file
51
tests/data/integritycheck/core.key
Normal file
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
28
tests/data/integritycheck/root.crt
Normal file
28
tests/data/integritycheck/root.crt
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIE1DCCArygAwIBAgIUFgEnT7tUWNgEKfbMiRTOm3Z8figwDQYJKoZIhvcNAQEF
|
||||
BQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMCAXDTE1MTEw
|
||||
MzIxMDMzMloYDzk5OTkxMjMxMjM1OTU5WjAjMSEwHwYDVQQKDBhvd25DbG91ZCBD
|
||||
b2RlIFNpZ25pbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCt
|
||||
rYEwiwpuhzRNx1L2SntkL/zalA7OkwEcsBn4Ysw47nEdvp648AVohT7d+U7+DWix
|
||||
O06xvlAJUhqYTXX7EG9n+mBnG+TIMq2zlei0Jj3uq1pEZE9elfGZael2uc8gRXMZ
|
||||
YFmSlTvzexqvfK4B3DwoZaMaWJecEO9iyuUyzHMBpE8bHtGDOUGy/oTO9WASbtl9
|
||||
Rfk38VLLV6csCPwKjii6Q3YZ+AYU0YqLg22BwZlqlTexUjWAmVIqaoxmSEuKa41X
|
||||
nuAIHfP65oiob86s4IvJXVr3r7NjdF2IJ/ZrwmjGKaWgSZKcoZBPLArZJeJiIQ4Y
|
||||
KzLZATwba5dWswV0mbDj8eP2BG+02NVKxylOBbeoBESnahZeZ5nJ5XKZr+ErJAUW
|
||||
b417fEnYaQNBlNnijjkqXaDipmTktUfnv4lm30sUAgho6I3Ga7gQrFPzKg9V4j2S
|
||||
+LOTc1HmJOnR6Kfttx+yAHYLKtvV5yIMMpz+rZ2X5g/N2GdgleZj5VU9nmKzTPeG
|
||||
x6V+dBaIkqNe8/AXaVnxt9KSb03Q/+CFjKTNDtEN5fNJuXS0+h+oop6nhpktM2i7
|
||||
gCpxeLNEaQaeoxR5093VN00oOJOYBvQoVGEDftEwdG6dWbTZsIykBF7aK+p8DMy9
|
||||
tCdc2GnGMEuFlUNA9ucv2Rv7IcuPdspnK31CZoMNKwIDAQABMA0GCSqGSIb3DQEB
|
||||
BQUAA4ICAQBROWec0HOsnLPN40gkBQ62mNBUJgcAr5K2eMIEMSRFRD2ldEVOvmCO
|
||||
u1Q62umy9tiSRiFQTcG1J9k0zlOjy/hfpBl2G1Zce0OoEeuNkH7c0W/idHSloWRZ
|
||||
YlK3tVJD6DzY6s9VbO6e/ncecNsXkirkWp/cvMYquH2d4OmSl0/hW0VMdxOCLxkA
|
||||
xbW+3Dh05u7tgKVRD67/GRvLtg+xHaOJqiOh3MpMaHy+6xT5Fd5K2QC0pcGtZuqF
|
||||
EnnfdeUI/Dy76yQE8pBfjaUFf3TS1n1E6kun1Nkf0X4pvwi8W1goLsPu5sWDNNga
|
||||
1RGYj0o5OdIo27qebfmu76WX0fNNd47VabtzNV+W7Msj0yeZg+hxAtAvs0ZEyJh+
|
||||
4biWsv+ALSlqz4sSdoOVGUEBdnkUrWN19lou62ix9vTmuCrVEA3TuZA3PR0+hqqQ
|
||||
/A/DcmWwxWYKyaBgxwHc/nGo1qWrDh22P5Rp7++Zw3kOCY6QmeJkAiHFs6Crw4ub
|
||||
HKVMw3fV5H9oiUFjadPZoCU51uXKX4YRqKxWJ5djlp4r1GCEQHyxngTsmH3komnw
|
||||
kh4LsEQRqdhuT0A4sZN7CenMJfQiFqupL7RVSycJFQpgzwVFmOzjCVT4PT/W5ARv
|
||||
9YtqEkvyoRTwErwuN/FIVvhWnIP/C69Z1/T/nXyj86P2G7PMgnchIQ==
|
||||
-----END CERTIFICATE-----
|
51
tests/data/integritycheck/root.key
Normal file
51
tests/data/integritycheck/root.key
Normal file
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
247
tests/lib/command/integrity/SignAppTest.php
Normal file
247
tests/lib/command/integrity/SignAppTest.php
Normal file
|
@ -0,0 +1,247 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
namespace Test\Command\Integrity;
|
||||
|
||||
use OC\Core\Command\Integrity\SignApp;
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use Test\TestCase;
|
||||
|
||||
class SignAppTest extends TestCase {
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
/** @var SignApp */
|
||||
private $signApp;
|
||||
/** @var FileAccessHelper */
|
||||
private $fileAccessHelper;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->fileAccessHelper = $this->getMockBuilder('\OC\IntegrityCheck\Helpers\FileAccessHelper')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->signApp = new SignApp(
|
||||
$this->checker,
|
||||
$this->fileAccessHelper
|
||||
);
|
||||
}
|
||||
|
||||
public function testExecuteWithMissingAppId() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('appId')
|
||||
->will($this->returnValue(null));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('PrivateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('Certificate'));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('--appId, --privateKey and --certificate are required.');
|
||||
|
||||
$this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecuteWithMissingPrivateKey() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('appId')
|
||||
->will($this->returnValue('AppId'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(null));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('Certificate'));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('--appId, --privateKey and --certificate are required.');
|
||||
|
||||
$this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecuteWithMissingCertificate() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('appId')
|
||||
->will($this->returnValue('AppId'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('--appId, --privateKey and --certificate are required.');
|
||||
|
||||
$this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecuteWithNotExistingPrivateKey() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('appId')
|
||||
->will($this->returnValue('AppId'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('Private key "privateKey" does not exists.');
|
||||
|
||||
$this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecuteWithNotExistingCertificate() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('appId')
|
||||
->will($this->returnValue('AppId'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.key'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with('certificate')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('Certificate "certificate" does not exists.');
|
||||
|
||||
$this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecute() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('appId')
|
||||
->will($this->returnValue('AppId'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.key'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with('certificate')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.crt'));
|
||||
|
||||
$this->checker
|
||||
->expects($this->once())
|
||||
->method('writeAppSignature');
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('Successfully signed "AppId"');
|
||||
|
||||
$this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
}
|
194
tests/lib/command/integrity/SignCoreTest.php
Normal file
194
tests/lib/command/integrity/SignCoreTest.php
Normal file
|
@ -0,0 +1,194 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
namespace Test\Command\Integrity;
|
||||
|
||||
use OC\Core\Command\Integrity\SignCore;
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use Test\TestCase;
|
||||
|
||||
class SignCoreTest extends TestCase {
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
/** @var SignCore */
|
||||
private $signCore;
|
||||
/** @var FileAccessHelper */
|
||||
private $fileAccessHelper;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->fileAccessHelper = $this->getMockBuilder('\OC\IntegrityCheck\Helpers\FileAccessHelper')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->signCore = new SignCore(
|
||||
$this->checker,
|
||||
$this->fileAccessHelper
|
||||
);
|
||||
}
|
||||
|
||||
public function testExecuteWithMissingPrivateKey() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(null));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('Certificate'));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('--privateKey and --certificate are required.');
|
||||
|
||||
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecuteWithMissingCertificate() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('--privateKey and --certificate are required.');
|
||||
|
||||
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecuteWithNotExistingPrivateKey() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('Private key "privateKey" does not exists.');
|
||||
|
||||
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecuteWithNotExistingCertificate() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.key'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with('certificate')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('Certificate "certificate" does not exists.');
|
||||
|
||||
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
||||
public function testExecute() {
|
||||
$inputInterface = $this->getMock('\Symfony\Component\Console\Input\InputInterface');
|
||||
$outputInterface = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
|
||||
|
||||
$inputInterface
|
||||
->expects($this->at(0))
|
||||
->method('getOption')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue('privateKey'));
|
||||
$inputInterface
|
||||
->expects($this->at(1))
|
||||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with('privateKey')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.key'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with('certificate')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.crt'));
|
||||
|
||||
$this->checker
|
||||
->expects($this->once())
|
||||
->method('writeCoreSignature');
|
||||
|
||||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('Successfully signed "core"');
|
||||
|
||||
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
}
|
671
tests/lib/integritycheck/checkertest.php
Normal file
671
tests/lib/integritycheck/checkertest.php
Normal file
|
@ -0,0 +1,671 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Test\IntegrityCheck;
|
||||
|
||||
use OC\IntegrityCheck\Checker;
|
||||
use OC\Memcache\NullCache;
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\File\X509;
|
||||
use Test\TestCase;
|
||||
use OC\IntegrityCheck\Helpers\EnvironmentHelper;
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use OC\IntegrityCheck\Helpers\AppLocator;
|
||||
use OCP\IConfig;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\App\IAppManager;
|
||||
|
||||
class CheckerTest extends TestCase {
|
||||
/** @var EnvironmentHelper */
|
||||
private $environmentHelper;
|
||||
/** @var AppLocator */
|
||||
private $appLocator;
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
/** @var FileAccessHelper */
|
||||
private $fileAccessHelper;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
/** @var ICacheFactory */
|
||||
private $cacheFactory;
|
||||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->environmentHelper = $this->getMock('\OC\IntegrityCheck\Helpers\EnvironmentHelper');
|
||||
$this->fileAccessHelper = $this->getMock('\OC\IntegrityCheck\Helpers\FileAccessHelper');
|
||||
$this->appLocator = $this->getMock('\OC\IntegrityCheck\Helpers\AppLocator');
|
||||
$this->config = $this->getMock('\OCP\IConfig');
|
||||
$this->cacheFactory = $this->getMock('\OCP\ICacheFactory');
|
||||
$this->appManager = $this->getMock('\OCP\App\IAppManager');
|
||||
|
||||
$this->cacheFactory
|
||||
->expects($this->any())
|
||||
->method('create')
|
||||
->with('oc.integritycheck.checker')
|
||||
->will($this->returnValue(new NullCache()));
|
||||
|
||||
$this->checker = new Checker(
|
||||
$this->environmentHelper,
|
||||
$this->fileAccessHelper,
|
||||
$this->appLocator,
|
||||
$this->config,
|
||||
$this->cacheFactory,
|
||||
$this->appManager
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage Directory name must not be empty.
|
||||
*/
|
||||
public function testWriteAppSignatureOfNotExistingApp() {
|
||||
$keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
|
||||
$rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($rsaPrivateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$this->checker->writeAppSignature('NotExistingApp', $x509, $rsa);
|
||||
}
|
||||
|
||||
public function testWriteAppSignature() {
|
||||
$expectedSignatureFileData = '{
|
||||
"hashes": {
|
||||
"AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
|
||||
"subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
|
||||
},
|
||||
"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=",
|
||||
"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-----"
|
||||
}';
|
||||
$this->appLocator
|
||||
->expects($this->once())
|
||||
->method('getAppPath')
|
||||
->with('SomeExistingApp')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->once())
|
||||
->method('file_put_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//appinfo/signature.json',
|
||||
$expectedSignatureFileData
|
||||
);
|
||||
|
||||
$keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
|
||||
$rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($rsaPrivateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$this->checker->writeAppSignature('SomeExistingApp', $x509, $rsa);
|
||||
}
|
||||
|
||||
public function testVerifyAppSignatureWithoutSignatureData() {
|
||||
$expected = [
|
||||
'EXCEPTION' => [
|
||||
'class' => 'OC\IntegrityCheck\Exceptions\InvalidSignatureException',
|
||||
'message' => 'Signature data not found.',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp'));
|
||||
}
|
||||
|
||||
public function testVerifyAppSignatureWithValidSignatureData() {
|
||||
$this->appLocator
|
||||
->expects($this->once())
|
||||
->method('getAppPath')
|
||||
->with('SomeApp')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$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/app//appinfo/signature.json'
|
||||
)
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
'/resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$this->assertSame([], $this->checker->verifyAppSignature('SomeApp'));
|
||||
}
|
||||
|
||||
public function testVerifyAppSignatureWithTamperedSignatureData() {
|
||||
$this->appLocator
|
||||
->expects($this->once())
|
||||
->method('getAppPath')
|
||||
->with('SomeApp')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$signatureDataFile = '{
|
||||
"hashes": {
|
||||
"AnotherFile.txt": "tampered",
|
||||
"subfolder\/file.txt": "tampered"
|
||||
},
|
||||
"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=",
|
||||
"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-----"
|
||||
}';
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//appinfo/signature.json'
|
||||
)
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
'/resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$expected = [
|
||||
'EXCEPTION' => [
|
||||
'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
|
||||
'message' => 'Signature could not get verified.',
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expected, $this->checker->verifyAppSignature('SomeApp'));
|
||||
}
|
||||
|
||||
public function testVerifyAppSignatureWithTamperedFiles() {
|
||||
$this->appLocator
|
||||
->expects($this->once())
|
||||
->method('getAppPath')
|
||||
->with('SomeApp')
|
||||
->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//appinfo/signature.json'
|
||||
)
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
'/resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
|
||||
$expected = [
|
||||
'INVALID_HASH' => [
|
||||
'AnotherFile.txt' => [
|
||||
'expected' => '1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112',
|
||||
'current' => '7322348ba269c6d5522efe02f424fa3a0da319a7cd9c33142a5afe32a2d9af2da3a411f086fcfc96ff4301ea566f481dba0960c2abeef3594c4d930462f6584c',
|
||||
],
|
||||
],
|
||||
'FILE_MISSING' => [
|
||||
'subfolder/file.txt' => [
|
||||
'expected' => '410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b',
|
||||
'current' => '',
|
||||
],
|
||||
],
|
||||
'EXTRA_FILE' => [
|
||||
'UnecessaryFile' => [
|
||||
'expected' => '',
|
||||
'current' => 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
$this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp'));
|
||||
}
|
||||
|
||||
public function testVerifyAppWithDifferentScope() {
|
||||
$this->appLocator
|
||||
->expects($this->once())
|
||||
->method('getAppPath')
|
||||
->with('SomeApp')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/'));
|
||||
$signatureDataFile = '{
|
||||
"hashes": {
|
||||
"AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
|
||||
"subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
|
||||
},
|
||||
"signature": "eXesvDm3pkek12xSwMG10y9suRES79Nye3jYNe5KYq1tTUPqRRNgxmMGAfcUro0zpLeAr2YgHeSMWtglblGOW7pmwGVPZ0O1Y4r1fE6jnep0kW+35PLIaqCorIOnCAtSzDNKBhwd1ow3zW2wC0DFouuEkIO8u5Fw28g8E8dp8zEk1xMblNPy+xtWkmYHrVJ\/dQgun1bYOF2ZFtAzatwndTI\/bGsy1i3Wsl+x6HyWKQdq8y8VObtOqKDH7uERBEpB9DHVyKflj1v1gQuEH6BhaRdATc7ee0MiQdGblraIySwYRdfo2d8i82OVKrenMB3SLwyCvDPyQ9iKpTOnSF52ZBqaqSXKM2N\/RAkweeBFQQCwcHhqxvB0cfbyHcbkOLeCZe\/tsh68IxwTiYgzvLfl7sOZ5arnZbzrPpZmB+hfV2omkoJ1tDwOWz9hEmLLNtfo2OxyUH1m0+XFaC+Gbn4WkVDgf7YZkwUcG+Qoa3oKDNMss8MEyZxewl2iDGZcf402dlidHRprlfmXbAYuVQ08\/a0HxIKYPGh\/nsMGmwnO15CWtFpAbhUA\/D5oRjsIxnvXaMDg0iAFpdu\/5Ffsj7g3EPdBkiQHNYK7YU1RRx609eH0bZyiIYHdUPw7ikLupvrebZmELqi3mqDFO99u4eISlxFJlUbUND3L4BtmWTWrKwI=",
|
||||
"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-----"
|
||||
}';
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData//appinfo/signature.json')
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
'/resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$expected = [
|
||||
'EXCEPTION' => [
|
||||
'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
|
||||
'message' => 'Certificate is not valid for required scope. (Requested: SomeApp, current: CN=AnotherScope)',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->checker->verifyAppSignature('SomeApp'));
|
||||
}
|
||||
|
||||
public function testVerifyAppWithDifferentScopeAndAlwaysTrustedCore() {
|
||||
$this->appLocator
|
||||
->expects($this->once())
|
||||
->method('getAppPath')
|
||||
->with('SomeApp')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$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/app//appinfo/signature.json')
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
'/resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$this->assertSame([], $this->checker->verifyAppSignature('SomeApp'));
|
||||
}
|
||||
|
||||
public function testWriteCoreSignature() {
|
||||
$expectedSignatureFileData = '{
|
||||
"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->environmentHelper
|
||||
->expects($this->any())
|
||||
->method('getServerRoot')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->once())
|
||||
->method('file_put_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json',
|
||||
$expectedSignatureFileData
|
||||
);
|
||||
|
||||
$keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/core.crt');
|
||||
$rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/core.key');
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($rsaPrivateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$this->checker->writeCoreSignature($x509, $rsa);
|
||||
}
|
||||
|
||||
public function testVerifyCoreSignatureWithoutSignatureData() {
|
||||
$expected = [
|
||||
'EXCEPTION' => [
|
||||
'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
|
||||
'message' => 'Signature data not found.',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $this->checker->verifyCoreSignature());
|
||||
}
|
||||
|
||||
public function testVerifyCoreSignatureWithValidSignatureData() {
|
||||
$this->environmentHelper
|
||||
->expects($this->any())
|
||||
->method('getServerRoot')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$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/app//core/signature.json'
|
||||
)
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$this->assertSame([], $this->checker->verifyCoreSignature());
|
||||
}
|
||||
|
||||
public function testVerifyCoreSignatureWithValidSignatureDataAndNotAlphabeticOrder() {
|
||||
$this->environmentHelper
|
||||
->expects($this->any())
|
||||
->method('getServerRoot')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$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/app//core/signature.json'
|
||||
)
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$this->assertSame([], $this->checker->verifyCoreSignature());
|
||||
}
|
||||
|
||||
public function testVerifyCoreSignatureWithTamperedSignatureData() {
|
||||
$this->environmentHelper
|
||||
->expects($this->any())
|
||||
->method('getServerRoot')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/appWithInvalidData/'));
|
||||
$signatureDataFile = '{
|
||||
"hashes": {
|
||||
"AnotherFile.txt": "tampered",
|
||||
"subfolder\/file.txt": "tampered"
|
||||
},
|
||||
"signature": "eXesvDm3pkek12xSwMG10y9suRES79Nye3jYNe5KYq1tTUPqRRNgxmMGAfcUro0zpLeAr2YgHeSMWtglblGOW7pmwGVPZ0O1Y4r1fE6jnep0kW+35PLIaqCorIOnCAtSzDNKBhwd1ow3zW2wC0DFouuEkIO8u5Fw28g8E8dp8zEk1xMblNPy+xtWkmYHrVJ\/dQgun1bYOF2ZFtAzatwndTI\/bGsy1i3Wsl+x6HyWKQdq8y8VObtOqKDH7uERBEpB9DHVyKflj1v1gQuEH6BhaRdATc7ee0MiQdGblraIySwYRdfo2d8i82OVKrenMB3SLwyCvDPyQ9iKpTOnSF52ZBqaqSXKM2N\/RAkweeBFQQCwcHhqxvB0cfbyHcbkOLeCZe\/tsh68IxwTiYgzvLfl7sOZ5arnZbzrPpZmB+hfV2omkoJ1tDwOWz9hEmLLNtfo2OxyUH1m0+XFaC+Gbn4WkVDgf7YZkwUcG+Qoa3oKDNMss8MEyZxewl2iDGZcf402dlidHRprlfmXbAYuVQ08\/a0HxIKYPGh\/nsMGmwnO15CWtFpAbhUA\/D5oRjsIxnvXaMDg0iAFpdu\/5Ffsj7g3EPdBkiQHNYK7YU1RRx609eH0bZyiIYHdUPw7ikLupvrebZmELqi3mqDFO99u4eISlxFJlUbUND3L4BtmWTWrKwI=",
|
||||
"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 = [
|
||||
'EXCEPTION' => [
|
||||
'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
|
||||
'message' => 'Signature could not get verified.',
|
||||
]
|
||||
];
|
||||
$this->assertSame($expected, $this->checker->verifyCoreSignature());
|
||||
}
|
||||
|
||||
public function testVerifyCoreSignatureWithTamperedFiles() {
|
||||
$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 = [
|
||||
'INVALID_HASH' => [
|
||||
'AnotherFile.txt' => [
|
||||
'expected' => '1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112',
|
||||
'current' => '7322348ba269c6d5522efe02f424fa3a0da319a7cd9c33142a5afe32a2d9af2da3a411f086fcfc96ff4301ea566f481dba0960c2abeef3594c4d930462f6584c',
|
||||
],
|
||||
],
|
||||
'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->any())
|
||||
->method('getServerRoot')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$signatureDataFile = '{
|
||||
"hashes": {
|
||||
"AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
|
||||
"subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
|
||||
},
|
||||
"signature": "eXesvDm3pkek12xSwMG10y9suRES79Nye3jYNe5KYq1tTUPqRRNgxmMGAfcUro0zpLeAr2YgHeSMWtglblGOW7pmwGVPZ0O1Y4r1fE6jnep0kW+35PLIaqCorIOnCAtSzDNKBhwd1ow3zW2wC0DFouuEkIO8u5Fw28g8E8dp8zEk1xMblNPy+xtWkmYHrVJ\/dQgun1bYOF2ZFtAzatwndTI\/bGsy1i3Wsl+x6HyWKQdq8y8VObtOqKDH7uERBEpB9DHVyKflj1v1gQuEH6BhaRdATc7ee0MiQdGblraIySwYRdfo2d8i82OVKrenMB3SLwyCvDPyQ9iKpTOnSF52ZBqaqSXKM2N\/RAkweeBFQQCwcHhqxvB0cfbyHcbkOLeCZe\/tsh68IxwTiYgzvLfl7sOZ5arnZbzrPpZmB+hfV2omkoJ1tDwOWz9hEmLLNtfo2OxyUH1m0+XFaC+Gbn4WkVDgf7YZkwUcG+Qoa3oKDNMss8MEyZxewl2iDGZcf402dlidHRprlfmXbAYuVQ08\/a0HxIKYPGh\/nsMGmwnO15CWtFpAbhUA\/D5oRjsIxnvXaMDg0iAFpdu\/5Ffsj7g3EPdBkiQHNYK7YU1RRx609eH0bZyiIYHdUPw7ikLupvrebZmELqi3mqDFO99u4eISlxFJlUbUND3L4BtmWTWrKwI=",
|
||||
"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-----"
|
||||
}';
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json'
|
||||
)
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$expected = [
|
||||
'EXCEPTION' => [
|
||||
'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
|
||||
'message' => 'Certificate is not valid.',
|
||||
]
|
||||
];
|
||||
$this->assertSame($expected, $this->checker->verifyCoreSignature());
|
||||
}
|
||||
|
||||
public function testVerifyCoreWithDifferentScope() {
|
||||
$this->environmentHelper
|
||||
->expects($this->any())
|
||||
->method('getServerRoot')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/app/'));
|
||||
$signatureDataFile = '{
|
||||
"hashes": {
|
||||
"AnotherFile.txt": "1570ca9420e37629de4328f48c51da29840ddeaa03ae733da4bf1d854b8364f594aac560601270f9e1797ed4cd57c1aea87bf44cf4245295c94f2e935a2f0112",
|
||||
"subfolder\/file.txt": "410738545fb623c0a5c8a71f561e48ea69e3ada0981a455e920a5ae9bf17c6831ae654df324f9328ff8453de179276ae51931cca0fa71fe8ccde6c083ca0574b"
|
||||
},
|
||||
"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=",
|
||||
"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-----"
|
||||
}';
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//core/signature.json'
|
||||
)
|
||||
->will($this->returnValue($signatureDataFile));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_get_contents')
|
||||
->with(
|
||||
\OC::$SERVERROOT . '/tests/data/integritycheck/app//resources/codesigning/root.crt'
|
||||
)
|
||||
->will($this->returnValue(file_get_contents(__DIR__ .'/../../data/integritycheck/root.crt')));
|
||||
|
||||
$expected = [
|
||||
'EXCEPTION' => [
|
||||
'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException',
|
||||
'message' => 'Certificate is not valid for required scope. (Requested: core, current: CN=SomeApp)',
|
||||
]
|
||||
];
|
||||
$this->assertSame($expected, $this->checker->verifyCoreSignature());
|
||||
}
|
||||
|
||||
public function testRunInstanceVerification() {
|
||||
$this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
|
||||
->setConstructorArgs([
|
||||
$this->environmentHelper,
|
||||
$this->fileAccessHelper,
|
||||
$this->appLocator,
|
||||
$this->config,
|
||||
$this->cacheFactory,
|
||||
$this->appManager,
|
||||
])
|
||||
->setMethods([
|
||||
'verifyCoreSignature',
|
||||
'verifyAppSignature',
|
||||
])
|
||||
->getMock();
|
||||
|
||||
$this->checker
|
||||
->expects($this->at(0))
|
||||
->method('verifyCoreSignature');
|
||||
$this->appLocator
|
||||
->expects($this->at(0))
|
||||
->Method('getAllApps')
|
||||
->will($this->returnValue([
|
||||
'files',
|
||||
'calendar',
|
||||
'contacts',
|
||||
'dav',
|
||||
]));
|
||||
$this->appManager
|
||||
->expects($this->at(0))
|
||||
->method('isShipped')
|
||||
->with('files')
|
||||
->will($this->returnValue(true));
|
||||
$this->checker
|
||||
->expects($this->at(1))
|
||||
->method('verifyAppSignature')
|
||||
->with('files');
|
||||
$this->appManager
|
||||
->expects($this->at(1))
|
||||
->method('isShipped')
|
||||
->with('calendar')
|
||||
->will($this->returnValue(false));
|
||||
$this->appLocator
|
||||
->expects($this->at(1))
|
||||
->method('getAppPath')
|
||||
->with('calendar')
|
||||
->will($this->returnValue('/apps/calendar'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
->method('file_exists')
|
||||
->with('/apps/calendar/appinfo/signature.json')
|
||||
->will($this->returnValue(true));
|
||||
$this->checker
|
||||
->expects($this->at(2))
|
||||
->method('verifyAppSignature')
|
||||
->with('calendar');
|
||||
$this->appManager
|
||||
->expects($this->at(2))
|
||||
->method('isShipped')
|
||||
->with('contacts')
|
||||
->will($this->returnValue(false));
|
||||
$this->appLocator
|
||||
->expects($this->at(2))
|
||||
->method('getAppPath')
|
||||
->with('contacts')
|
||||
->will($this->returnValue('/apps/contacts'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(1))
|
||||
->method('file_exists')
|
||||
->with('/apps/contacts/appinfo/signature.json')
|
||||
->will($this->returnValue(false));
|
||||
$this->appManager
|
||||
->expects($this->at(3))
|
||||
->method('isShipped')
|
||||
->with('dav')
|
||||
->will($this->returnValue(true));
|
||||
$this->checker
|
||||
->expects($this->at(3))
|
||||
->method('verifyAppSignature')
|
||||
->with('dav');
|
||||
|
||||
$this->checker->runInstanceVerification();
|
||||
}
|
||||
|
||||
}
|
51
tests/lib/integritycheck/helpers/AppLocatorTest.php
Normal file
51
tests/lib/integritycheck/helpers/AppLocatorTest.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Test\IntegrityCheck\Helpers;
|
||||
|
||||
use OC\IntegrityCheck\Helpers\AppLocator;
|
||||
use Test\TestCase;
|
||||
|
||||
class AppLocatorTest extends TestCase {
|
||||
/** @var AppLocator */
|
||||
private $locator;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->locator = new AppLocator();
|
||||
}
|
||||
|
||||
public function testGetAppPath() {
|
||||
$this->assertSame(\OC_App::getAppPath('files'), $this->locator->getAppPath('files'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage App not found
|
||||
*/
|
||||
public function testGetAppPathNotExistentApp() {
|
||||
$this->locator->getAppPath('aTotallyNotExistingApp');
|
||||
}
|
||||
|
||||
public function testGetAllApps() {
|
||||
$this->assertSame(\OC_App::getAllApps(), $this->locator->getAllApps());
|
||||
}
|
||||
}
|
32
tests/lib/integritycheck/helpers/EnvironmentHelperTest.php
Normal file
32
tests/lib/integritycheck/helpers/EnvironmentHelperTest.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Test\IntegrityCheck\Factories;
|
||||
|
||||
use OC\IntegrityCheck\Helpers\EnvironmentHelper;
|
||||
use Test\TestCase;
|
||||
|
||||
class EnvironmentHelperTest extends TestCase {
|
||||
public function testGetServerRoot() {
|
||||
$factory = new EnvironmentHelper();
|
||||
$this->assertSame(\OC::$SERVERROOT, $factory->getServerRoot());
|
||||
}
|
||||
}
|
43
tests/lib/integritycheck/helpers/FileAccessHelperTest.php
Normal file
43
tests/lib/integritycheck/helpers/FileAccessHelperTest.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
namespace Test\IntegrityCheck\Helpers;
|
||||
|
||||
use OC\IntegrityCheck\Helpers\FileAccessHelper;
|
||||
use Test\TestCase;
|
||||
|
||||
class FileAccessHelperTest extends TestCase {
|
||||
/** @var FileAccessHelper */
|
||||
private $fileAccessHelper;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->fileAccessHelper = new FileAccessHelper();
|
||||
}
|
||||
|
||||
public function testReadAndWrite() {
|
||||
$tempManager = \OC::$server->getTempManager();
|
||||
$filePath = $tempManager->getTemporaryFile();
|
||||
$data = 'SomeDataGeneratedByIntegrityCheck';
|
||||
|
||||
$this->fileAccessHelper->file_put_contents($filePath, $data);
|
||||
$this->assertSame($data, $this->fileAccessHelper->file_get_contents($filePath));
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ namespace OC;
|
|||
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
use OC\IntegrityCheck\Checker;
|
||||
|
||||
class UpdaterTest extends \Test\TestCase {
|
||||
/** @var IConfig */
|
||||
|
@ -34,6 +35,8 @@ class UpdaterTest extends \Test\TestCase {
|
|||
private $logger;
|
||||
/** @var Updater */
|
||||
private $updater;
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
@ -46,10 +49,14 @@ class UpdaterTest extends \Test\TestCase {
|
|||
$this->logger = $this->getMockBuilder('\\OCP\\ILogger')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->updater = new Updater(
|
||||
$this->httpHelper,
|
||||
$this->config,
|
||||
$this->checker,
|
||||
$this->logger
|
||||
);
|
||||
}
|
||||
|
@ -158,11 +165,11 @@ class UpdaterTest extends \Test\TestCase {
|
|||
*
|
||||
* @param string $oldVersion
|
||||
* @param string $newVersion
|
||||
* @param string $allowedVersion
|
||||
* @param bool $result
|
||||
*/
|
||||
public function testIsUpgradePossible($oldVersion, $newVersion, $allowedVersion, $result) {
|
||||
$updater = new Updater($this->httpHelper, $this->config, $this->logger);
|
||||
$this->assertSame($result, $updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersion));
|
||||
$this->assertSame($result, $this->updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersion));
|
||||
}
|
||||
|
||||
public function testCheckInCache() {
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue