Skip to content

Commit

Permalink
Change to re-create masterkeys
Browse files Browse the repository at this point in the history
This change will help users to recreate masterkey
for encryption.

Signed-off-by: Sujith H <sharidasan@owncloud.com>
  • Loading branch information
sharidas committed Jun 20, 2017
1 parent acd5c8d commit a022e0b
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 10 deletions.
11 changes: 10 additions & 1 deletion apps/encryption/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,16 @@
'name' => 'Status#getStatus',
'url' => '/ajax/getStatus',
'verb' => 'GET'
],
[
'name' => 'MasterKey#createNewMasterKey',
'url' => '/ajax/createNewMasterKey',
'verb' => 'POST'
],
[
'name' => 'MasterKey#reencryptFiles',
'url' => '/ajax/reencryptFiles',
'verb' => 'POST'
]


]]);
15 changes: 15 additions & 0 deletions apps/encryption/js/settings-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ $(document).ready(function () {
$("#encryptHomeStorage, #encryptionSetRecoveryKey").addClass("hidden");
if($("#encryptionType").val().length === 0) {
$("#encryptionType").text("Encryption type: Master Key");
$("#newMasterKey").toggleClass('hidden');
$("#reEncryptFS").toggleClass('hidden');
}
}
} else if (encryptionType === "customkey") {
Expand Down Expand Up @@ -80,6 +82,19 @@ $(document).ready(function () {
}
});

$("#newMasterKey").click(function () {
$.post(
OC.generateUrl('/apps/encryption/ajax/createNewMasterKey')
);
});

$("#reEncryptFS").click(function () {
$.post(
OC.generateUrl('/apps/encryption/ajax/reencryptFiles')
);
});


$('input:button[name="enableRecoveryKey"]').click(function () {

var recoveryStatus = $(this).attr('status');
Expand Down
14 changes: 14 additions & 0 deletions apps/encryption/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@


use OC\Files\View;
use OCA\Encryption\Controller\MasterKeyController;
use OCA\Encryption\Controller\RecoveryController;
use OCA\Encryption\Controller\SettingsController;
use OCA\Encryption\Controller\StatusController;
Expand Down Expand Up @@ -196,6 +197,19 @@ function (IAppContainer $c) {
);
});

$container->registerService('MasterKeyController', function (IAppContainer $c) {
$server = $c->getServer();
return new MasterKeyController(
$c->getAppName(),
$server->getRequest(),
$c->query('Manager'),
$c->query('IUserManager'),
$c->query('View'),
$c->query('KeyManager'),
$c->query('Util')
);
});

$container->registerService('SettingsController', function (IAppContainer $c) {
$server = $c->getServer();
return new SettingsController(
Expand Down
261 changes: 261 additions & 0 deletions apps/encryption/lib/Controller/MasterKeyController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
<?php
/**
* @author Sujith Haridasan <sharidasan@owncloud.com>
*
* @copyright Copyright (c) 2017, ownCloud GmbH
* @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 OCA\Encryption\Controller;

use OC\Encryption\Exceptions\DecryptionFailedException;
use OC\Encryption\Manager;
use OC\Files\View;
use OCA\Encryption\KeyManager;
use OCA\Encryption\Util;
use OCP\AppFramework\Controller;
use OCP\IRequest;
use OCP\IUserManager;


class MasterKeyController extends Controller {

/** @var Manager */
private $encryptionManager;

/** @var IUserManager */
private $userManager;

/** @var View */
private $rootView;

/** @var KeyManager */
private $keyManager;

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

/** @var array files which couldn't be decrypted */
protected $failed;


/**
* MasterKeyController constructor.
*
* @param string $appName
* @param IRequest $request
* @param Manager $encryptionManager
* @param IUserManager $userManager
* @param View $rootView
* @param KeyManager $keyManager
* @param Util $util
*/
public function __construct(
$appName, IRequest $request, Manager $encryptionManager,
IUserManager $userManager, View $rootView,
KeyManager $keyManager, Util $util) {
parent::__construct($appName, $request);
$this->encryptionManager = $encryptionManager;
$this->userManager = $userManager;
$this->rootView = $rootView;
$this->keyManager = $keyManager;
$this->util = $util;
}

public function createNewMasterKey() {
\OC::$server->getLogger()->warning(__METHOD__." so time to create new key!!!", ['app' => __CLASS__]);
// First decrypt the users files
$this->decryptAllUsersFiles();

if (empty($this->failed)) {
//Now recreate new encryption
//Delete the encryption app
\OC::$server->getAppConfig()->deleteApp('encryption');
//Delete the files_encryption dir
$this->rootView->deleteAll('files_encryption');
\OC::$server->getConfig()->deleteAppValue('files_encryption','installed_version');
\OC::$server->getConfig()->deleteAppValues('encryption');

//Re-enable the encryption app
\OC_App::enable('encryption');
//Set masterkey it.
\OC::$server->getAppConfig()->setValue('encryption','useMasterKey', '1');
}

}

public function reencryptFiles() {
//Now encrypt FS again
$this->keyManager->validateMasterKey();
$this->encryptAllUsersFiles();
}

public function encryptAllUsersFiles() {
$this->encryptAllUserFilesWithMasterKey();
}

public function encryptAllUserFilesWithMasterKey() {
$userNo = 1;
foreach($this->userManager->getBackends() as $backend) {
$limit = 500;
$offset = 0;
do {
$users = $backend->getUsers('', $limit, $offset);
foreach ($users as $user) {
echo "\n Entering user $user\n";
$userCount = "$user ($userNo)";
$this->encryptUsersFiles($user, $userCount);
$userNo++;
}
$offset += $limit;
} while(count($users) >= $limit);
}
}

public function encryptUsersFiles($uid, $userCount) {

$this->setupUserFS($uid);
$directories = [];
$directories[] = '/' . $uid . '/files';

while($root = array_pop($directories)) {
$content = $this->rootView->getDirectoryContent($root);
foreach ($content as $file) {
$path = $root . '/' . $file['name'];
if ($this->rootView->is_dir($path)) {
$directories[] = $path;
continue;
} else {
if($this->encryptFile($path) === false) {
}
}
}
}
}

public function encryptFile($path) {
$source = $path;
$target = $path . '.encrypted.' . time();

try {
\OC::$server->getSession()->set('encryptAllCmd', true);
$this->rootView->copy($source, $target);
$this->rootView->rename($target, $source);
\OC::$server->getSession()->set('encryptAllCmd', true);
} catch (DecryptionFailedException $e) {
if ($this->rootView->file_exists($target)) {
$this->rootView->unlink($target);
}
return false;
}

return true;
}

public function decryptAllUsersFiles() {
$userList = [];

foreach ($this->userManager->getBackends() as $backend) {
$limit = 500;
$offset = 0;
do {
$users = $backend->getUsers('', $limit, $offset);
foreach ($users as $user) {
$userList[] = $user;
}
$offset += $limit;
} while (count($users) >= $limit);
}

$numberOfUsers = count($userList);
$userNo = 1;
foreach ($userList as $uid) {
$userCount = "$uid ($userNo of $numberOfUsers)";
$this->decryptUsersFiles($uid, $userCount);
$userNo++;
}
}

public function decryptUsersFiles($uid, $userCount) {

$this->setupUserFS($uid);
$directories = [];
$directories[] = '/' . $uid . '/files';

while ($root = array_pop($directories)) {
$content = $this->rootView->getDirectoryContent($root);
foreach ($content as $file) {
// only decrypt files owned by the user
if($file->getStorage()->instanceOfStorage('OCA\Files_Sharing\SharedStorage')) {
continue;
}
$path = $root . '/' . $file['name'];
if ($this->rootView->is_dir($path)) {
$directories[] = $path;
continue;
} else {
try {
if ($file->isEncrypted() === false) {
} else {
if ($this->decryptFile($path) === false) {
}
}
} catch (\Exception $e) {
if (isset($this->failed[$uid])) {
$this->failed[$uid][] = $path;
} else {
$this->failed[$uid] = [$path];
}
}
}
}
}

if (empty($this->failed)) {
$this->rootView->deleteAll("$uid/files_encryption");
}
}

protected function decryptFile($path) {

$source = $path;
$target = $path . '.decrypted.' . $this->getTimestamp();

try {
\OC::$server->getSession()->set('decryptAllCmd', true);
$this->rootView->copy($source, $target);
$this->rootView->rename($target, $source);
\OC::$server->getSession()->remove('decryptAllCmd');
} catch (DecryptionFailedException $e) {
if ($this->rootView->file_exists($target)) {
$this->rootView->unlink($target);
}
return false;
}

return true;
}

protected function getTimestamp() {
return time();
}


protected function setupUserFS($uid) {
\OC_Util::tearDownFS();
\OC_Util::setupFS($uid);
}
}
4 changes: 3 additions & 1 deletion apps/encryption/lib/Crypto/Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,9 @@ public function symmetricDecryptFileContent($keyFileContents, $passPhrase, $ciph
private function checkSignature($data, $passPhrase, $expectedSignature) {
$signature = $this->createSignature($data, $passPhrase);
if (!hash_equals($expectedSignature, $signature)) {
throw new HintException('Bad Signature', $this->l->t('Bad Signature'));
if (\OC::$server->getAppConfig()->getValue('encryption', 'useMasterKey', 0) === 0) {
throw new HintException('Bad Signature', $this->l->t('Bad Signature'));
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions apps/encryption/lib/Crypto/EncryptAll.php
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,10 @@ protected function encryptFile($path) {
$target = $path . '.encrypted.' . time();

try {
\OC::$server->getSession()->set('encryptAllCmd', true);
$this->rootView->copy($source, $target);
$this->rootView->rename($target, $source);
\OC::$server->getSession()->set('encryptAllCmd', true);
} catch (DecryptionFailedException $e) {
if ($this->rootView->file_exists($target)) {
$this->rootView->unlink($target);
Expand Down
2 changes: 2 additions & 0 deletions apps/encryption/templates/settings-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
}
?>
</label>
<button id="newMasterKey" class="hidden"><?php p($l->t("Create new master key")); ?></button>
<button id="reEncryptFS" class="hidden"><?php p($l->t("Encrypt files")); ?></button>
<span id="encryptionKeySelection">
<select id="keyTypeId" name="keyType">
<option value="nokey"><?php p($l->t("Please select an encryption option"))?></option>
Expand Down
Loading

0 comments on commit a022e0b

Please sign in to comment.