diff --git a/apps/encryption/appinfo/application.php b/apps/encryption/appinfo/application.php index 6080a29d5f..c7c8d2a3d3 100644 --- a/apps/encryption/appinfo/application.php +++ b/apps/encryption/appinfo/application.php @@ -242,6 +242,7 @@ class Application extends \OCP\AppFramework\App { $c->getServer()->getUserManager(), new View(), $c->query('KeyManager'), + $c->query('Util'), $server->getConfig(), $server->getMailer(), $server->getL10N('encryption'), diff --git a/apps/encryption/lib/crypto/encryptall.php b/apps/encryption/lib/crypto/encryptall.php index 18e93d2e12..0037c21326 100644 --- a/apps/encryption/lib/crypto/encryptall.php +++ b/apps/encryption/lib/crypto/encryptall.php @@ -28,12 +28,12 @@ use OC\Encryption\Exceptions\DecryptionFailedException; use OC\Files\View; use OCA\Encryption\KeyManager; use OCA\Encryption\Users\Setup; +use OCA\Encryption\Util; use OCP\IConfig; use OCP\IL10N; use OCP\IUserManager; use OCP\Mail\IMailer; use OCP\Security\ISecureRandom; -use OCP\Util; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Helper\Table; @@ -55,6 +55,9 @@ class EncryptAll { /** @var KeyManager */ protected $keyManager; + /** @var Util */ + protected $util; + /** @var array */ protected $userPasswords; @@ -84,6 +87,7 @@ class EncryptAll { * @param IUserManager $userManager * @param View $rootView * @param KeyManager $keyManager + * @param Util $util * @param IConfig $config * @param IMailer $mailer * @param IL10N $l @@ -95,6 +99,7 @@ class EncryptAll { IUserManager $userManager, View $rootView, KeyManager $keyManager, + Util $util, IConfig $config, IMailer $mailer, IL10N $l, @@ -105,6 +110,7 @@ class EncryptAll { $this->userManager = $userManager; $this->rootView = $rootView; $this->keyManager = $keyManager; + $this->util = $util; $this->config = $config; $this->mailer = $mailer; $this->l = $l; @@ -129,16 +135,21 @@ class EncryptAll { $this->output->writeln("\n"); $this->output->writeln($headline); $this->output->writeln(str_pad('', strlen($headline), '=')); - - //create private/public keys for each user and store the private key password $this->output->writeln("\n"); - $this->output->writeln('Create key-pair for every user'); - $this->output->writeln('------------------------------'); - $this->output->writeln(''); - $this->output->writeln('This module will encrypt all files in the users files folder initially.'); - $this->output->writeln('Already existing versions and files in the trash bin will not be encrypted.'); - $this->output->writeln(''); - $this->createKeyPairs(); + + if ($this->util->isMasterKeyEnabled()) { + $this->output->writeln('Use master key to encrypt all files.'); + $this->keyManager->validateMasterKey(); + } else { + //create private/public keys for each user and store the private key password + $this->output->writeln('Create key-pair for every user'); + $this->output->writeln('------------------------------'); + $this->output->writeln(''); + $this->output->writeln('This module will encrypt all files in the users files folder initially.'); + $this->output->writeln('Already existing versions and files in the trash bin will not be encrypted.'); + $this->output->writeln(''); + $this->createKeyPairs(); + } //setup users file system and encrypt all files one by one (take should encrypt setting of storage into account) $this->output->writeln("\n"); @@ -146,12 +157,14 @@ class EncryptAll { $this->output->writeln('----------------------------'); $this->output->writeln(''); $this->encryptAllUsersFiles(); - //send-out or display password list and write it to a file - $this->output->writeln("\n"); - $this->output->writeln('Generated encryption key passwords'); - $this->output->writeln('----------------------------------'); - $this->output->writeln(''); - $this->outputPasswords(); + if ($this->util->isMasterKeyEnabled() === false) { + //send-out or display password list and write it to a file + $this->output->writeln("\n"); + $this->output->writeln('Generated encryption key passwords'); + $this->output->writeln('----------------------------------'); + $this->output->writeln(''); + $this->outputPasswords(); + } $this->output->writeln("\n"); } @@ -200,16 +213,42 @@ class EncryptAll { $progress->start(); $numberOfUsers = count($this->userPasswords); $userNo = 1; - foreach ($this->userPasswords as $uid => $password) { - $userCount = "$uid ($userNo of $numberOfUsers)"; - $this->encryptUsersFiles($uid, $progress, $userCount); - $userNo++; + if ($this->util->isMasterKeyEnabled()) { + $this->encryptAllUserFilesWithMasterKey($progress); + } else { + foreach ($this->userPasswords as $uid => $password) { + $userCount = "$uid ($userNo of $numberOfUsers)"; + $this->encryptUsersFiles($uid, $progress, $userCount); + $userNo++; + } } $progress->setMessage("all files encrypted"); $progress->finish(); } + /** + * encrypt all user files with the master key + * + * @param ProgressBar $progress + */ + protected function encryptAllUserFilesWithMasterKey(ProgressBar $progress) { + $userNo = 1; + foreach($this->userManager->getBackends() as $backend) { + $limit = 500; + $offset = 0; + do { + $users = $backend->getUsers('', $limit, $offset); + foreach ($users as $user) { + $userCount = "$user ($userNo)"; + $this->encryptUsersFiles($user, $progress, $userCount); + $userNo++; + } + $offset += $limit; + } while(count($users) >= $limit); + } + } + /** * encrypt files from the given user * @@ -384,7 +423,7 @@ class EncryptAll { $message->setHtmlBody($htmlBody); $message->setPlainBody($textBody); $message->setFrom([ - Util::getDefaultEmailAddress('admin-noreply') + \OCP\Util::getDefaultEmailAddress('admin-noreply') ]); $this->mailer->send($message); diff --git a/apps/encryption/lib/keymanager.php b/apps/encryption/lib/keymanager.php index 5cce760fa5..4f22c3def6 100644 --- a/apps/encryption/lib/keymanager.php +++ b/apps/encryption/lib/keymanager.php @@ -394,17 +394,20 @@ class KeyManager { public function getFileKey($path, $uid) { $encryptedFileKey = $this->keyStorage->getFileKey($path, $this->fileKeyId, Encryption::ID); + if (empty($encryptedFileKey)) { + return ''; + } + + if ($this->util->isMasterKeyEnabled()) { + $uid = $this->getMasterKeyId(); + } + if (is_null($uid)) { $uid = $this->getPublicShareKeyId(); $shareKey = $this->getShareKey($path, $uid); $privateKey = $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.privateKey', Encryption::ID); $privateKey = $this->crypt->decryptPrivateKey($privateKey); } else { - - if ($this->util->isMasterKeyEnabled()) { - $uid = $this->getMasterKeyId(); - } - $shareKey = $this->getShareKey($path, $uid); $privateKey = $this->session->getPrivateKey(); } diff --git a/apps/encryption/tests/lib/crypto/encryptalltest.php b/apps/encryption/tests/lib/crypto/encryptalltest.php index 04d931342a..d31f58377c 100644 --- a/apps/encryption/tests/lib/crypto/encryptalltest.php +++ b/apps/encryption/tests/lib/crypto/encryptalltest.php @@ -31,6 +31,9 @@ class EncryptAllTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject | \OCA\Encryption\KeyManager */ protected $keyManager; + /** @var \PHPUnit_Framework_MockObject_MockObject | \OCA\Encryption\Util */ + protected $util; + /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IUserManager */ protected $userManager; @@ -73,6 +76,8 @@ class EncryptAllTest extends TestCase { ->disableOriginalConstructor()->getMock(); $this->keyManager = $this->getMockBuilder('OCA\Encryption\KeyManager') ->disableOriginalConstructor()->getMock(); + $this->util = $this->getMockBuilder('OCA\Encryption\Util') + ->disableOriginalConstructor()->getMock(); $this->userManager = $this->getMockBuilder('OCP\IUserManager') ->disableOriginalConstructor()->getMock(); $this->view = $this->getMockBuilder('OC\Files\View') @@ -110,6 +115,7 @@ class EncryptAllTest extends TestCase { $this->userManager, $this->view, $this->keyManager, + $this->util, $this->config, $this->mailer, $this->l, @@ -127,6 +133,7 @@ class EncryptAllTest extends TestCase { $this->userManager, $this->view, $this->keyManager, + $this->util, $this->config, $this->mailer, $this->l, @@ -137,6 +144,7 @@ class EncryptAllTest extends TestCase { ->setMethods(['createKeyPairs', 'encryptAllUsersFiles', 'outputPasswords']) ->getMock(); + $this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(false); $encryptAll->expects($this->at(0))->method('createKeyPairs')->with(); $encryptAll->expects($this->at(1))->method('encryptAllUsersFiles')->with(); $encryptAll->expects($this->at(2))->method('outputPasswords')->with(); @@ -145,6 +153,36 @@ class EncryptAllTest extends TestCase { } + public function testEncryptAllWithMasterKey() { + /** @var EncryptAll | \PHPUnit_Framework_MockObject_MockObject $encryptAll */ + $encryptAll = $this->getMockBuilder('OCA\Encryption\Crypto\EncryptAll') + ->setConstructorArgs( + [ + $this->setupUser, + $this->userManager, + $this->view, + $this->keyManager, + $this->util, + $this->config, + $this->mailer, + $this->l, + $this->questionHelper, + $this->secureRandom + ] + ) + ->setMethods(['createKeyPairs', 'encryptAllUsersFiles', 'outputPasswords']) + ->getMock(); + + $this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(true); + $encryptAll->expects($this->never())->method('createKeyPairs'); + $this->keyManager->expects($this->once())->method('validateMasterKey'); + $encryptAll->expects($this->at(0))->method('encryptAllUsersFiles')->with(); + $encryptAll->expects($this->never())->method('outputPasswords'); + + $encryptAll->encryptAll($this->inputInterface, $this->outputInterface); + + } + public function testCreateKeyPairs() { /** @var EncryptAll | \PHPUnit_Framework_MockObject_MockObject $encryptAll */ $encryptAll = $this->getMockBuilder('OCA\Encryption\Crypto\EncryptAll') @@ -154,6 +192,7 @@ class EncryptAllTest extends TestCase { $this->userManager, $this->view, $this->keyManager, + $this->util, $this->config, $this->mailer, $this->l, @@ -202,6 +241,7 @@ class EncryptAllTest extends TestCase { $this->userManager, $this->view, $this->keyManager, + $this->util, $this->config, $this->mailer, $this->l, @@ -212,6 +252,8 @@ class EncryptAllTest extends TestCase { ->setMethods(['encryptUsersFiles']) ->getMock(); + $this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(false); + // set protected property $output $this->invokePrivate($encryptAll, 'output', [$this->outputInterface]); $this->invokePrivate($encryptAll, 'userPasswords', [['user1' => 'pwd1', 'user2' => 'pwd2']]); @@ -232,6 +274,7 @@ class EncryptAllTest extends TestCase { $this->userManager, $this->view, $this->keyManager, + $this->util, $this->config, $this->mailer, $this->l, @@ -239,9 +282,10 @@ class EncryptAllTest extends TestCase { $this->secureRandom ] ) - ->setMethods(['encryptFile']) + ->setMethods(['encryptFile', 'setupUserFS']) ->getMock(); + $this->util->expects($this->any())->method('isMasterKeyEnabled')->willReturn(false); $this->view->expects($this->at(0))->method('getDirectoryContent') ->with('/user1/files')->willReturn( @@ -268,8 +312,8 @@ class EncryptAllTest extends TestCase { } ); - $encryptAll->expects($this->at(0))->method('encryptFile')->with('/user1/files/bar'); - $encryptAll->expects($this->at(1))->method('encryptFile')->with('/user1/files/foo/subfile'); + $encryptAll->expects($this->at(1))->method('encryptFile')->with('/user1/files/bar'); + $encryptAll->expects($this->at(2))->method('encryptFile')->with('/user1/files/foo/subfile'); $progressBar = $this->getMockBuilder('Symfony\Component\Console\Helper\ProgressBar') ->disableOriginalConstructor()->getMock();