mirror of
https://github.com/nextcloud/server.git
synced 2026-03-28 21:33:40 -04:00
moving methods to their final places
and updating test some.
This commit is contained in:
parent
1b42b492dc
commit
e6dc6944c2
6 changed files with 188 additions and 127 deletions
|
|
@ -127,7 +127,8 @@ class Application extends \OCP\AppFramework\App {
|
|||
$server->getConfig(),
|
||||
$server->getUserSession(),
|
||||
$server->getSession(),
|
||||
$server->getLogger()
|
||||
$server->getLogger(),
|
||||
$c->query('Recovery')
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -168,13 +169,7 @@ class Application extends \OCP\AppFramework\App {
|
|||
function (IAppContainer $c) {
|
||||
$server = $c->getServer();
|
||||
|
||||
return new Util(new View(),
|
||||
new Filesystem(),
|
||||
$c->query('Crypt'),
|
||||
$c->query('KeyManager'),
|
||||
$server->getLogger(),
|
||||
$server->getUserSession(),
|
||||
$server->getConfig()
|
||||
return new Util(new View(), $c->query('Crypt'), $c->query('KeyManager'), $server->getLogger(), $server->getUserSession(), $server->getConfig()
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ use OC\Encryption\Exceptions\PrivateKeyMissingException;
|
|||
use OC\Encryption\Exceptions\PublicKeyMissingException;
|
||||
use OCA\Encryption\Crypto\Crypt;
|
||||
use OCP\Encryption\Keys\IStorage;
|
||||
use OCP\ICache;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
use OCP\IUserSession;
|
||||
|
|
@ -86,6 +84,10 @@ class KeyManager {
|
|||
* @var ILogger
|
||||
*/
|
||||
private $log;
|
||||
/**
|
||||
* @var Recovery
|
||||
*/
|
||||
private $recovery;
|
||||
|
||||
/**
|
||||
* @param IStorage $keyStorage
|
||||
|
|
@ -94,6 +96,7 @@ class KeyManager {
|
|||
* @param IUserSession $userSession
|
||||
* @param \OCP\ISession $session
|
||||
* @param ILogger $log
|
||||
* @param Recovery $recovery
|
||||
*/
|
||||
public function __construct(
|
||||
IStorage $keyStorage,
|
||||
|
|
@ -101,7 +104,9 @@ class KeyManager {
|
|||
IConfig $config,
|
||||
IUserSession $userSession,
|
||||
ISession $session,
|
||||
ILogger $log) {
|
||||
ILogger $log,
|
||||
Recovery $recovery
|
||||
) {
|
||||
|
||||
self::$session = $session;
|
||||
$this->keyStorage = $keyStorage;
|
||||
|
|
@ -115,7 +120,9 @@ class KeyManager {
|
|||
|
||||
if (empty($this->publicShareKeyId)) {
|
||||
$this->publicShareKeyId = 'pubShare_' . substr(md5(time()), 0, 8);
|
||||
$this->config->setAppValue('encryption', 'publicShareKeyId', $this->publicShareKeyId);
|
||||
$this->config->setAppValue('encryption',
|
||||
'publicShareKeyId',
|
||||
$this->publicShareKeyId);
|
||||
|
||||
$keyPair = $this->crypt->createKeyPair();
|
||||
|
||||
|
|
@ -125,9 +132,11 @@ class KeyManager {
|
|||
$keyPair['publicKey']);
|
||||
|
||||
// Encrypt private key empty passphrase
|
||||
$encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'], '');
|
||||
$encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'],
|
||||
'');
|
||||
if ($encryptedKey) {
|
||||
$this->keyStorage->setSystemUserKey($this->publicShareKeyId . '.privateKey', $encryptedKey);
|
||||
$this->keyStorage->setSystemUserKey($this->publicShareKeyId . '.privateKey',
|
||||
$encryptedKey);
|
||||
} else {
|
||||
$this->log->error('Could not create public share keys');
|
||||
}
|
||||
|
|
@ -136,6 +145,7 @@ class KeyManager {
|
|||
|
||||
$this->keyId = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : false;
|
||||
$this->log = $log;
|
||||
$this->recovery = $recovery;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -386,7 +396,7 @@ class KeyManager {
|
|||
$this->setPrivateKey($user, $encryptedKey);
|
||||
|
||||
if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
|
||||
$util->recoverUsersFiles($recoveryPassword);
|
||||
$this->recovery->recoverUsersFiles($recoveryPassword);
|
||||
}
|
||||
} else {
|
||||
$this->log->error('Encryption Could not update users encryption password');
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ use OCP\IUser;
|
|||
use OCP\IUserSession;
|
||||
use OCP\PreConditionNotMetException;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use OCP\Share;
|
||||
|
||||
class Recovery {
|
||||
|
||||
|
|
@ -54,10 +55,12 @@ class Recovery {
|
|||
*/
|
||||
private $config;
|
||||
/**
|
||||
* @var IEncryptionKeyStorage
|
||||
* @var IStorage
|
||||
*/
|
||||
private $keyStorage;
|
||||
|
||||
private $recoveryKeyId;
|
||||
|
||||
/**
|
||||
* @param IUserSession $user
|
||||
* @param Crypt $crypt
|
||||
|
|
@ -90,7 +93,9 @@ class Recovery {
|
|||
|
||||
if ($recoveryKeyId === null) {
|
||||
$recoveryKeyId = $this->random->getLowStrengthGenerator();
|
||||
$appConfig->setAppValue('encryption', 'recoveryKeyId', $recoveryKeyId);
|
||||
$appConfig->setAppValue('encryption',
|
||||
'recoveryKeyId',
|
||||
$recoveryKeyId);
|
||||
}
|
||||
|
||||
$keyManager = $this->keyManager;
|
||||
|
|
@ -98,7 +103,9 @@ class Recovery {
|
|||
if (!$keyManager->recoveryKeyExists()) {
|
||||
$keyPair = $this->crypt->createKeyPair();
|
||||
|
||||
return $this->keyManager->storeKeyPair($this->user->getUID(), $password, $keyPair);
|
||||
return $this->keyManager->storeKeyPair($this->user->getUID(),
|
||||
$password,
|
||||
$keyPair);
|
||||
}
|
||||
|
||||
if ($keyManager->checkRecoveryPassword($password)) {
|
||||
|
|
@ -143,6 +150,7 @@ class Recovery {
|
|||
|
||||
return ($recoveryMode === '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $enabled
|
||||
* @return bool
|
||||
|
|
@ -165,12 +173,79 @@ class Recovery {
|
|||
* @param $recoveryPassword
|
||||
*/
|
||||
public function recoverUsersFiles($recoveryPassword) {
|
||||
// todo: get system private key here
|
||||
// $this->keyManager->get
|
||||
$encryptedKey = $this->keyManager->getSystemPrivateKey();
|
||||
|
||||
$privateKey = $this->crypt->decryptPrivateKey($encryptedKey,
|
||||
$recoveryPassword);
|
||||
|
||||
$this->recoverAllFiles('/', $privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $privateKey
|
||||
*/
|
||||
private function recoverAllFiles($path, $privateKey) {
|
||||
$dirContent = $this->files->getDirectoryContent($path);
|
||||
|
||||
foreach ($dirContent as $item) {
|
||||
// Get relative path from encryption/keyfiles
|
||||
$filePath = substr($item['path'], strlen('encryption/keys'));
|
||||
if ($this->files->is_dir($this->user->getUID() . '/files' . '/' . $filePath)) {
|
||||
$this->recoverAllFiles($filePath . '/', $privateKey);
|
||||
} else {
|
||||
$this->recoverFile($filePath, $privateKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filePath
|
||||
* @param $privateKey
|
||||
*/
|
||||
private function recoverFile($filePath, $privateKey) {
|
||||
$sharingEnabled = Share::isEnabled();
|
||||
$uid = $this->user->getUID();
|
||||
|
||||
// Find out who, if anyone, is sharing the file
|
||||
if ($sharingEnabled) {
|
||||
$result = Share::getUsersSharingFile($filePath,
|
||||
$uid,
|
||||
true);
|
||||
$userIds = $result['users'];
|
||||
$userIds[] = 'public';
|
||||
} else {
|
||||
$userIds = [
|
||||
$uid,
|
||||
$this->recoveryKeyId
|
||||
];
|
||||
}
|
||||
$filteredUids = $this->filterShareReadyUsers($userIds);
|
||||
|
||||
// Decrypt file key
|
||||
$encKeyFile = $this->keyManager->getFileKey($filePath,
|
||||
$uid);
|
||||
|
||||
$shareKey = $this->keyManager->getShareKey($filePath,
|
||||
$uid);
|
||||
|
||||
$plainKeyFile = $this->crypt->multiKeyDecrypt($encKeyFile,
|
||||
$shareKey,
|
||||
$privateKey);
|
||||
|
||||
// Encrypt the file key again to all users, this time with the new publick keyt for the recovered user
|
||||
$userPublicKeys = $this->keyManager->getPublicKeys($filteredUids['ready']);
|
||||
$multiEncryptionKey = $this->crypt->multiKeyEncrypt($plainKeyFile,
|
||||
$userPublicKeys);
|
||||
|
||||
$this->keyManager->setFileKey($multiEncryptionKey['data'],
|
||||
$uid);
|
||||
|
||||
$this->keyManager->setShareKey($filePath,
|
||||
$uid,
|
||||
$multiEncryptionKey['keys']);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ namespace OCA\Encryption;
|
|||
use OC\Files\Filesystem;
|
||||
use OC\Files\View;
|
||||
use OCA\Encryption\Crypto\Crypt;
|
||||
use OCA\Files_Versions\Storage;
|
||||
use OCP\App;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
|
|
@ -40,10 +39,6 @@ class Util {
|
|||
* @var View
|
||||
*/
|
||||
private $files;
|
||||
/**
|
||||
* @var Filesystem
|
||||
*/
|
||||
private $filesystem;
|
||||
/**
|
||||
* @var Crypt
|
||||
*/
|
||||
|
|
@ -69,24 +64,20 @@ class Util {
|
|||
* Util constructor.
|
||||
*
|
||||
* @param View $files
|
||||
* @param Filesystem $filesystem
|
||||
* @param Crypt $crypt
|
||||
* @param KeyManager $keyManager
|
||||
* @param ILogger $logger
|
||||
* @param IUserSession $userSession
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(
|
||||
View $files,
|
||||
Filesystem $filesystem,
|
||||
Crypt $crypt,
|
||||
KeyManager $keyManager,
|
||||
ILogger $logger,
|
||||
IUserSession $userSession,
|
||||
IConfig $config
|
||||
public function __construct(View $files,
|
||||
Crypt $crypt,
|
||||
KeyManager $keyManager,
|
||||
ILogger $logger,
|
||||
IUserSession $userSession,
|
||||
IConfig $config
|
||||
) {
|
||||
$this->files = $files;
|
||||
$this->filesystem = $filesystem;
|
||||
$this->crypt = $crypt;
|
||||
$this->keyManager = $keyManager;
|
||||
$this->logger = $logger;
|
||||
|
|
@ -94,16 +85,6 @@ class Util {
|
|||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filePath
|
||||
* @return array
|
||||
*/
|
||||
private function splitPath($filePath) {
|
||||
$normalized = $this->filesystem->normalizePath($filePath);
|
||||
|
||||
return explode('/', $normalized);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
|
@ -154,71 +135,5 @@ class Util {
|
|||
return $this->files->file_exists($uid . '/files');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $privateKey
|
||||
*/
|
||||
private function recoverAllFiles($path, $privateKey) {
|
||||
// Todo relocate to storage
|
||||
$dirContent = $this->files->getDirectoryContent($path);
|
||||
|
||||
foreach ($dirContent as $item) {
|
||||
// Get relative path from encryption/keyfiles
|
||||
$filePath = substr($item['path'], strlen('encryption/keys'));
|
||||
if ($this->files->is_dir($this->user->getUID() . '/files' . '/' . $filePath)) {
|
||||
$this->recoverAllFiles($filePath . '/', $privateKey);
|
||||
} else {
|
||||
$this->recoverFile($filePath, $privateKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filePath
|
||||
* @param $privateKey
|
||||
*/
|
||||
private function recoverFile($filePath, $privateKey) {
|
||||
$sharingEnabled = Share::isEnabled();
|
||||
$uid = $this->user->getUID();
|
||||
|
||||
// Find out who, if anyone, is sharing the file
|
||||
if ($sharingEnabled) {
|
||||
$result = Share::getUsersSharingFile($filePath,
|
||||
$uid,
|
||||
true);
|
||||
$userIds = $result['users'];
|
||||
$userIds[] = 'public';
|
||||
} else {
|
||||
$userIds = [
|
||||
$uid,
|
||||
$this->recoveryKeyId
|
||||
];
|
||||
}
|
||||
$filteredUids = $this->filterShareReadyUsers($userIds);
|
||||
|
||||
// Decrypt file key
|
||||
$encKeyFile = $this->keyManager->getFileKey($filePath,
|
||||
$uid);
|
||||
|
||||
$shareKey = $this->keyManager->getShareKey($filePath,
|
||||
$uid);
|
||||
|
||||
$plainKeyFile = $this->crypt->multiKeyDecrypt($encKeyFile,
|
||||
$shareKey,
|
||||
$privateKey);
|
||||
|
||||
// Encrypt the file key again to all users, this time with the new publick keyt for the recovered user
|
||||
$userPublicKeys = $this->keyManager->getPublicKeys($filteredUids['ready']);
|
||||
$multiEncryptionKey = $this->crypt->multiKeyEncrypt($plainKeyFile,
|
||||
$userPublicKeys);
|
||||
|
||||
$this->keyManager->setFileKey($multiEncryptionKey['data'],
|
||||
$uid);
|
||||
|
||||
$this->keyManager->setShareKey($filePath,
|
||||
$uid,
|
||||
$multiEncryptionKey['keys']);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,20 +20,14 @@ $keymanager = new \OCA\Encryption\KeyManager(
|
|||
\OC::$server->getConfig(),
|
||||
\OC::$server->getUserSession(),
|
||||
\OC::$server->getSession(),
|
||||
\OC::$server->getLogger());
|
||||
\OC::$server->getLogger(),);
|
||||
|
||||
$user = \OCP\User::getUser();
|
||||
|
||||
$view = new \OC\Files\View('/');
|
||||
|
||||
$util = new \OCA\Encryption\Util(
|
||||
new \OC\Files\View(),
|
||||
new \OC\Files\Filesystem(),
|
||||
$crypt,
|
||||
$keymanager,
|
||||
\OC::$server->getLogger(),
|
||||
\OC::$server->getUserSession(),
|
||||
\OC::$server->getConfig());
|
||||
new \OC\Files\View(), $crypt, $keymanager, \OC::$server->getLogger(), \OC::$server->getUserSession(), \OC::$server->getConfig());
|
||||
|
||||
$session = \OC::$server->getSession();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,26 +10,64 @@
|
|||
namespace OCA\Encryption\Tests;
|
||||
|
||||
|
||||
use OC\Files\View;
|
||||
use OCA\Encryption\KeyManager;
|
||||
use Test\TestCase;
|
||||
|
||||
class KeyManagerTest extends TestCase {
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private static $trashbinState;
|
||||
/**
|
||||
* @var KeyManager
|
||||
*/
|
||||
private $instance;
|
||||
/**
|
||||
* @var
|
||||
* @var string
|
||||
*/
|
||||
private $userId;
|
||||
private static $testUser = 'test-keyManager-user.dot';
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $dummyKeys;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $userId;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $userPassword;
|
||||
/**
|
||||
* @var \OC\Files\View
|
||||
*/
|
||||
private $view;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dataDir;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static function setUpBeforeClass() {
|
||||
parent::setUpBeforeClass();
|
||||
|
||||
// Remember files_trashbin state
|
||||
self::$trashbinState = \OC_App::isEnabled('files_trashbin');
|
||||
|
||||
// We dont want tests with app files_trashbin enabled
|
||||
\OC_App::disable('files_trashbin');
|
||||
|
||||
$userManager = \OC::$server->getUserManager();
|
||||
$userManager->createUser(self::$testUser,
|
||||
self::$testUser);
|
||||
|
||||
// Create test user
|
||||
parent::loginAsUser(self::$testUser);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$keyStorageMock = $this->getMock('OCP\Encryption\Keys\IStorage');
|
||||
|
|
@ -47,18 +85,52 @@ class KeyManagerTest extends TestCase {
|
|||
->will($this->returnValue('admin'));
|
||||
$sessionMock = $this->getMock('OCP\ISession');
|
||||
$logMock = $this->getMock('OCP\ILogger');
|
||||
$this->userId = 'admin';
|
||||
$recoveryMock = $this->getMockBuilder('OCA\Encryption\Recovery')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->instance = new KeyManager($keyStorageMock,
|
||||
$cryptMock,
|
||||
$configMock,
|
||||
$userMock,
|
||||
$sessionMock,
|
||||
$logMock);
|
||||
$logMock,
|
||||
$recoveryMock);
|
||||
|
||||
$this->dummyKeys = ['public' => 'randomweakpublickeyhere',
|
||||
'private' => 'randomweakprivatekeyhere'];
|
||||
self::loginAsUser(self::$testUser);
|
||||
$this->userId = self::$testUser;
|
||||
$this->userPassword = self::$testUser;
|
||||
$this->view = new View('/');
|
||||
|
||||
$this->dummyKeys = [
|
||||
'privateKey' => 'superinsecureprivatekey',
|
||||
'publicKey' => 'superinsecurepublickey'
|
||||
];
|
||||
|
||||
|
||||
$userManager = \OC::$server->getUserManager();
|
||||
|
||||
$userHome = $userManager->get($this->userId)->getHome();
|
||||
|
||||
$this->dataDir = str_replace('/' . $this->userId, '', $userHome);
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
parent::tearDown();
|
||||
$this->view->deleteAll('/' . self::$testUser . '/files_encryption/keys');
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
parent::tearDownAfterClass();
|
||||
// Cleanup Test user
|
||||
\OC::$server->getUserManager()->get(self::$testUser)->delete();
|
||||
// Reset app files_trashbin
|
||||
if (self::$trashbinState) {
|
||||
\OC_App::enable('files_trashbin');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @expectedException \OC\Encryption\Exceptions\PrivateKeyMissingException
|
||||
*/
|
||||
|
|
@ -93,7 +165,7 @@ class KeyManagerTest extends TestCase {
|
|||
public function testSetPublicKey() {
|
||||
|
||||
$this->assertTrue($this->instance->setPublicKey($this->userId,
|
||||
$this->dummyKeys['public']));
|
||||
$this->dummyKeys['publicKey']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -101,7 +173,7 @@ class KeyManagerTest extends TestCase {
|
|||
*/
|
||||
public function testSetPrivateKey() {
|
||||
$this->assertTrue($this->instance->setPrivateKey($this->userId,
|
||||
$this->dummyKeys['private']));
|
||||
$this->dummyKeys['privateKey']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue