You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DecryptAll.php 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Björn Schießle <bjoern@schiessle.org>
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. *
  8. * @license AGPL-3.0
  9. *
  10. * This code is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License, version 3,
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License, version 3,
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>
  21. *
  22. */
  23. namespace OCA\Encryption\Crypto;
  24. use OCA\Encryption\KeyManager;
  25. use OCA\Encryption\Session;
  26. use OCA\Encryption\Util;
  27. use Symfony\Component\Console\Helper\QuestionHelper;
  28. use Symfony\Component\Console\Input\InputInterface;
  29. use Symfony\Component\Console\Output\OutputInterface;
  30. use Symfony\Component\Console\Question\ConfirmationQuestion;
  31. use Symfony\Component\Console\Question\Question;
  32. class DecryptAll {
  33. /** @var Util */
  34. protected $util;
  35. /** @var QuestionHelper */
  36. protected $questionHelper;
  37. /** @var Crypt */
  38. protected $crypt;
  39. /** @var KeyManager */
  40. protected $keyManager;
  41. /** @var Session */
  42. protected $session;
  43. /**
  44. * @param Util $util
  45. * @param KeyManager $keyManager
  46. * @param Crypt $crypt
  47. * @param Session $session
  48. * @param QuestionHelper $questionHelper
  49. */
  50. public function __construct(
  51. Util $util,
  52. KeyManager $keyManager,
  53. Crypt $crypt,
  54. Session $session,
  55. QuestionHelper $questionHelper
  56. ) {
  57. $this->util = $util;
  58. $this->keyManager = $keyManager;
  59. $this->crypt = $crypt;
  60. $this->session = $session;
  61. $this->questionHelper = $questionHelper;
  62. }
  63. /**
  64. * prepare encryption module to decrypt all files
  65. *
  66. * @param InputInterface $input
  67. * @param OutputInterface $output
  68. * @param $user
  69. * @return bool
  70. */
  71. public function prepare(InputInterface $input, OutputInterface $output, $user) {
  72. $question = new Question('Please enter the recovery key password: ');
  73. if ($this->util->isMasterKeyEnabled()) {
  74. $output->writeln('Use master key to decrypt all files');
  75. $user = $this->keyManager->getMasterKeyId();
  76. $password = $this->keyManager->getMasterKeyPassword();
  77. } else {
  78. $recoveryKeyId = $this->keyManager->getRecoveryKeyId();
  79. if (!empty($user)) {
  80. $output->writeln('You can only decrypt the users files if you know');
  81. $output->writeln('the users password or if he activated the recovery key.');
  82. $output->writeln('');
  83. $questionUseLoginPassword = new ConfirmationQuestion(
  84. 'Do you want to use the users login password to decrypt all files? (y/n) ',
  85. false
  86. );
  87. $useLoginPassword = $this->questionHelper->ask($input, $output, $questionUseLoginPassword);
  88. if ($useLoginPassword) {
  89. $question = new Question('Please enter the user\'s login password: ');
  90. } elseif ($this->util->isRecoveryEnabledForUser($user) === false) {
  91. $output->writeln('No recovery key available for user ' . $user);
  92. return false;
  93. } else {
  94. $user = $recoveryKeyId;
  95. }
  96. } else {
  97. $output->writeln('You can only decrypt the files of all users if the');
  98. $output->writeln('recovery key is enabled by the admin and activated by the users.');
  99. $output->writeln('');
  100. $user = $recoveryKeyId;
  101. }
  102. $question->setHidden(true);
  103. $question->setHiddenFallback(false);
  104. $password = $this->questionHelper->ask($input, $output, $question);
  105. }
  106. $privateKey = $this->getPrivateKey($user, $password);
  107. if ($privateKey !== false) {
  108. $this->updateSession($user, $privateKey);
  109. return true;
  110. } else {
  111. $output->writeln('Could not decrypt private key, maybe you entered the wrong password?');
  112. }
  113. return false;
  114. }
  115. /**
  116. * get the private key which will be used to decrypt all files
  117. *
  118. * @param string $user
  119. * @param string $password
  120. * @return bool|string
  121. * @throws \OCA\Encryption\Exceptions\PrivateKeyMissingException
  122. */
  123. protected function getPrivateKey($user, $password) {
  124. $recoveryKeyId = $this->keyManager->getRecoveryKeyId();
  125. $masterKeyId = $this->keyManager->getMasterKeyId();
  126. if ($user === $recoveryKeyId) {
  127. $recoveryKey = $this->keyManager->getSystemPrivateKey($recoveryKeyId);
  128. $privateKey = $this->crypt->decryptPrivateKey($recoveryKey, $password);
  129. } elseif ($user === $masterKeyId) {
  130. $masterKey = $this->keyManager->getSystemPrivateKey($masterKeyId);
  131. $privateKey = $this->crypt->decryptPrivateKey($masterKey, $password, $masterKeyId);
  132. } else {
  133. $userKey = $this->keyManager->getPrivateKey($user);
  134. $privateKey = $this->crypt->decryptPrivateKey($userKey, $password, $user);
  135. }
  136. return $privateKey;
  137. }
  138. protected function updateSession($user, $privateKey) {
  139. $this->session->prepareDecryptAll($user, $privateKey);
  140. }
  141. }