Skip to content

Commit

Permalink
Merge pull request #39692 from fsamapoor/refactor_encryption_app_comm…
Browse files Browse the repository at this point in the history
…ands
  • Loading branch information
skjnldsv authored Aug 16, 2024
2 parents f4f7c75 + 6b795da commit 75180a6
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 193 deletions.
60 changes: 23 additions & 37 deletions apps/encryption/lib/Command/DisableMasterKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,15 @@
use Symfony\Component\Console\Question\ConfirmationQuestion;

class DisableMasterKey extends Command {

/** @var Util */
protected $util;

/** @var IConfig */
protected $config;

/** @var QuestionHelper */
protected $questionHelper;

/**
* @param Util $util
* @param IConfig $config
* @param QuestionHelper $questionHelper
*/
public function __construct(Util $util,
IConfig $config,
QuestionHelper $questionHelper) {
$this->util = $util;
$this->config = $config;
$this->questionHelper = $questionHelper;
public function __construct(
protected Util $util,
protected IConfig $config,
protected QuestionHelper $questionHelper,
) {
parent::__construct();
}

protected function configure() {
protected function configure(): void {
$this
->setName('encryption:disable-master-key')
->setDescription('Disable the master key and use per-user keys instead. Only available for fresh installations with no existing encrypted data! There is no way to enable it again.');
Expand All @@ -49,21 +33,23 @@ protected function execute(InputInterface $input, OutputInterface $output): int

if (!$isMasterKeyEnabled) {
$output->writeln('Master key already disabled');
} else {
$question = new ConfirmationQuestion(
'Warning: Only perform this operation for a fresh installations with no existing encrypted data! '
. 'There is no way to enable the master key again. '
. 'We strongly recommend to keep the master key, it provides significant performance improvements '
. 'and is easier to handle for both, users and administrators. '
. 'Do you really want to switch to per-user keys? (y/n) ', false);
if ($this->questionHelper->ask($input, $output, $question)) {
$this->config->setAppValue('encryption', 'useMasterKey', '0');
$output->writeln('Master key successfully disabled.');
} else {
$output->writeln('aborted.');
return 1;
}
return self::SUCCESS;
}
return 0;

$question = new ConfirmationQuestion(
'Warning: Only perform this operation for a fresh installations with no existing encrypted data! '
. 'There is no way to enable the master key again. '
. 'We strongly recommend to keep the master key, it provides significant performance improvements '
. 'and is easier to handle for both, users and administrators. '
. 'Do you really want to switch to per-user keys? (y/n) ', false);

if ($this->questionHelper->ask($input, $output, $question)) {
$this->config->setAppValue('encryption', 'useMasterKey', '0');
$output->writeln('Master key successfully disabled.');
return self::SUCCESS;
}

$output->writeln('aborted.');
return self::FAILURE;
}
}
4 changes: 2 additions & 2 deletions apps/encryption/lib/Command/DropLegacyFileKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int

if ($result) {
$output->writeln('All scanned files are properly encrypted.');
return 0;
return self::SUCCESS;
}

return 1;
return self::FAILURE;
}

private function scanFolder(OutputInterface $output, string $folder): bool {
Expand Down
52 changes: 19 additions & 33 deletions apps/encryption/lib/Command/EnableMasterKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,15 @@
use Symfony\Component\Console\Question\ConfirmationQuestion;

class EnableMasterKey extends Command {

/** @var Util */
protected $util;

/** @var IConfig */
protected $config;

/** @var QuestionHelper */
protected $questionHelper;

/**
* @param Util $util
* @param IConfig $config
* @param QuestionHelper $questionHelper
*/
public function __construct(Util $util,
IConfig $config,
QuestionHelper $questionHelper) {
$this->util = $util;
$this->config = $config;
$this->questionHelper = $questionHelper;
public function __construct(
protected Util $util,
protected IConfig $config,
protected QuestionHelper $questionHelper,
) {
parent::__construct();
}

protected function configure() {
protected function configure(): void {
$this
->setName('encryption:enable-master-key')
->setDescription('Enable the master key. Only available for fresh installations with no existing encrypted data! There is also no way to disable it again.');
Expand All @@ -51,18 +35,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int

if ($isAlreadyEnabled) {
$output->writeln('Master key already enabled');
} else {
$question = new ConfirmationQuestion(
'Warning: Only available for fresh installations with no existing encrypted data! '
return self::SUCCESS;
}

$question = new ConfirmationQuestion(
'Warning: Only available for fresh installations with no existing encrypted data! '
. 'There is also no way to disable it again. Do you want to continue? (y/n) ', false);
if ($this->questionHelper->ask($input, $output, $question)) {
$this->config->setAppValue('encryption', 'useMasterKey', '1');
$output->writeln('Master key successfully enabled.');
} else {
$output->writeln('aborted.');
return 1;
}

if ($this->questionHelper->ask($input, $output, $question)) {
$this->config->setAppValue('encryption', 'useMasterKey', '1');
$output->writeln('Master key successfully enabled.');
return self::SUCCESS;
}
return 0;

$output->writeln('aborted.');
return self::FAILURE;
}
}
42 changes: 21 additions & 21 deletions apps/encryption/lib/Command/FixEncryptedVersion.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
use Symfony\Component\Console\Output\OutputInterface;

class FixEncryptedVersion extends Command {
private bool $supportLegacy;
private bool $supportLegacy = false;

public function __construct(
private IConfig $config,
Expand All @@ -35,8 +35,6 @@ public function __construct(
private Util $util,
private View $view,
) {
$this->supportLegacy = false;

parent::__construct();
}

Expand Down Expand Up @@ -69,42 +67,44 @@ protected function execute(InputInterface $input, OutputInterface $output): int

if ($skipSignatureCheck) {
$output->writeln("<error>Repairing is not possible when \"encryption_skip_signature_check\" is set. Please disable this flag in the configuration.</error>\n");
return 1;
return self::FAILURE;
}

if (!$this->util->isMasterKeyEnabled()) {
$output->writeln("<error>Repairing only works with master key encryption.</error>\n");
return 1;
return self::FAILURE;
}

$user = $input->getArgument('user');
$all = $input->getOption('all');
$pathOption = \trim(($input->getOption('path') ?? ''), '/');

if (!$user && !$all) {
$output->writeln("Either a user id or --all needs to be provided");
return self::FAILURE;
}

if ($user) {
if ($all) {
$output->writeln("Specifying a user id and --all are mutually exclusive");
return 1;
return self::FAILURE;
}

if ($this->userManager->get($user) === null) {
$output->writeln("<error>User id $user does not exist. Please provide a valid user id</error>");
return 1;
return self::FAILURE;
}

return $this->runForUser($user, $pathOption, $output);
} elseif ($all) {
$result = 0;
$this->userManager->callForSeenUsers(function (IUser $user) use ($pathOption, $output, &$result) {
$output->writeln("Processing files for " . $user->getUID());
$result = $this->runForUser($user->getUID(), $pathOption, $output);
return $result === 0;
});
return $result;
} else {
$output->writeln("Either a user id or --all needs to be provided");
return 1;
}

$result = 0;
$this->userManager->callForSeenUsers(function (IUser $user) use ($pathOption, $output, &$result) {
$output->writeln("Processing files for " . $user->getUID());
$result = $this->runForUser($user->getUID(), $pathOption, $output);
return $result === 0;
});
return $result;
}

private function runForUser(string $user, string $pathOption, OutputInterface $output): int {
Expand All @@ -122,13 +122,13 @@ private function walkPathOfUser(string $user, string $path, OutputInterface $out
$this->setupUserFs($user);
if (!$this->view->file_exists($path)) {
$output->writeln("<error>Path \"$path\" does not exist. Please provide a valid path.</error>");
return 1;
return self::FAILURE;
}

if ($this->view->is_file($path)) {
$output->writeln("Verifying the content of file \"$path\"");
$this->verifyFileContent($path, $output);
return 0;
return self::SUCCESS;
}
$directories = [];
$directories[] = $path;
Expand All @@ -144,7 +144,7 @@ private function walkPathOfUser(string $user, string $path, OutputInterface $out
}
}
}
return 0;
return self::SUCCESS;
}

/**
Expand Down
46 changes: 7 additions & 39 deletions apps/encryption/lib/Command/FixKeyLocation.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,17 @@
use Symfony\Component\Console\Output\OutputInterface;

class FixKeyLocation extends Command {
private IUserManager $userManager;
private IUserMountCache $userMountCache;
private Util $encryptionUtil;
private IRootFolder $rootFolder;
private string $keyRootDirectory;
private View $rootView;
private Manager $encryptionManager;

public function __construct(
IUserManager $userManager,
IUserMountCache $userMountCache,
Util $encryptionUtil,
IRootFolder $rootFolder,
IManager $encryptionManager
private IUserManager $userManager,
private IUserMountCache $userMountCache,
private Util $encryptionUtil,
private IRootFolder $rootFolder,
IManager $encryptionManager,
) {
$this->userManager = $userManager;
$this->userMountCache = $userMountCache;
$this->encryptionUtil = $encryptionUtil;
$this->rootFolder = $rootFolder;
$this->keyRootDirectory = rtrim($this->encryptionUtil->getKeyStorageRoot(), '/');
$this->rootView = new View();
if (!$encryptionManager instanceof Manager) {
Expand Down Expand Up @@ -74,7 +66,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$user = $this->userManager->get($userId);
if (!$user) {
$output->writeln("<error>User $userId not found</error>");
return 1;
return self::FAILURE;
}

\OC_Util::setupFS($user->getUID());
Expand Down Expand Up @@ -158,7 +150,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}
}

return 0;
return self::SUCCESS;
}

private function getUserRelativePath(string $path): string {
Expand All @@ -171,7 +163,6 @@ private function getUserRelativePath(string $path): string {
}

/**
* @param IUser $user
* @return ICachedMountInfo[]
*/
private function getSystemMountsForUser(IUser $user): array {
Expand All @@ -186,7 +177,6 @@ private function getSystemMountsForUser(IUser $user): array {
/**
* Get all files in a folder which are marked as encrypted
*
* @param Folder $folder
* @return \Generator<File>
*/
private function getAllEncryptedFiles(Folder $folder) {
Expand Down Expand Up @@ -227,10 +217,6 @@ private function hasUserKey(IUser $user, Node $node): bool {

/**
* Check that the user key stored for a file can decrypt the file
*
* @param IUser $user
* @param File $node
* @return bool
*/
private function copyUserKeyToSystemAndValidate(IUser $user, File $node): bool {
$path = trim(substr($node->getPath(), strlen($user->getUID()) + 1), '/');
Expand Down Expand Up @@ -267,7 +253,6 @@ private function tryReadFile(File $node): bool {
/**
* Get the contents of a file without decrypting it
*
* @param File $node
* @return resource
*/
private function openWithoutDecryption(File $node, string $mode) {
Expand Down Expand Up @@ -295,9 +280,6 @@ private function openWithoutDecryption(File $node, string $mode) {

/**
* Check if the data stored for a file is encrypted, regardless of it's metadata
*
* @param File $node
* @return bool
*/
private function isDataEncrypted(File $node): bool {
$handle = $this->openWithoutDecryption($node, 'r');
Expand All @@ -310,9 +292,6 @@ private function isDataEncrypted(File $node): bool {

/**
* Attempt to find a key (stored for user) for a file (that needs a system key) even when it's not stored in the expected location
*
* @param File $node
* @return string
*/
private function findUserKeyForSystemFile(IUser $user, File $node): ?string {
$userKeyPath = $this->getUserBaseKeyPath($user);
Expand All @@ -328,8 +307,6 @@ private function findUserKeyForSystemFile(IUser $user, File $node): ?string {
/**
* Attempt to find a key for a file even when it's not stored in the expected location
*
* @param string $basePath
* @param string $name
* @return \Generator<string>
*/
private function findKeysByFileName(string $basePath, string $name) {
Expand All @@ -356,11 +333,6 @@ private function findKeysByFileName(string $basePath, string $name) {

/**
* Test if the provided key is valid as a system key for the file
*
* @param IUser $user
* @param string $key
* @param File $node
* @return bool
*/
private function testSystemKey(IUser $user, string $key, File $node): bool {
$systemKeyPath = $this->getSystemKeyPath($node);
Expand All @@ -378,10 +350,6 @@ private function testSystemKey(IUser $user, string $key, File $node): bool {

/**
* Decrypt a file with the specified system key and mark the key as not-encrypted
*
* @param File $node
* @param string $key
* @return void
*/
private function decryptWithSystemKey(File $node, string $key): void {
$storage = $node->getStorage();
Expand Down
Loading

0 comments on commit 75180a6

Please sign in to comment.