@@ -66,6 +66,11 @@ class Application extends \OCP\AppFramework\App { | |||
$session = $this->getContainer()->query('Session'); | |||
$session->setStatus(Session::RUN_MIGRATION); | |||
} | |||
if ($this->encryptionManager->isEnabled() && $encryptionSystemReady) { | |||
/** @var Setup $setup */ | |||
$setup = $this->getContainer()->query('UserSetup'); | |||
$setup->setupSystem(); | |||
} | |||
} | |||
/** |
@@ -117,22 +117,29 @@ class UserHooks implements IHook { | |||
public function addHooks() { | |||
OCUtil::connectHook('OC_User', 'post_login', $this, 'login'); | |||
OCUtil::connectHook('OC_User', 'logout', $this, 'logout'); | |||
OCUtil::connectHook('OC_User', | |||
'post_setPassword', | |||
$this, | |||
'setPassphrase'); | |||
OCUtil::connectHook('OC_User', | |||
'pre_setPassword', | |||
$this, | |||
'preSetPassphrase'); | |||
OCUtil::connectHook('OC_User', | |||
'post_createUser', | |||
$this, | |||
'postCreateUser'); | |||
OCUtil::connectHook('OC_User', | |||
'post_deleteUser', | |||
$this, | |||
'postDeleteUser'); | |||
// this hooks only make sense if no master key is used | |||
if ($this->util->isMasterKeyEnabled() === false) { | |||
OCUtil::connectHook('OC_User', | |||
'post_setPassword', | |||
$this, | |||
'setPassphrase'); | |||
OCUtil::connectHook('OC_User', | |||
'pre_setPassword', | |||
$this, | |||
'preSetPassphrase'); | |||
OCUtil::connectHook('OC_User', | |||
'post_createUser', | |||
$this, | |||
'postCreateUser'); | |||
OCUtil::connectHook('OC_User', | |||
'post_deleteUser', | |||
$this, | |||
'postDeleteUser'); | |||
} | |||
} | |||
@@ -151,12 +158,10 @@ class UserHooks implements IHook { | |||
// ensure filesystem is loaded | |||
if (!\OC\Files\Filesystem::$loaded) { | |||
\OC_Util::setupFS($params['uid']); | |||
$this->setupFS($params['uid']); | |||
} | |||
// setup user, if user not ready force relogin | |||
if (!$this->userSetup->setupUser($params['uid'], $params['password'])) { | |||
return false; | |||
if ($this->util->isMasterKeyEnabled() === false) { | |||
$this->userSetup->setupUser($params['uid'], $params['password']); | |||
} | |||
$this->keyManager->init($params['uid'], $params['password']); | |||
@@ -292,6 +297,15 @@ class UserHooks implements IHook { | |||
$password = $params['password']; | |||
$this->keyManager->replaceUserKeys($params['uid']); | |||
$this->userSetup->setupServerSide($params['uid'], $password); | |||
$this->userSetup->setupUser($params['uid'], $password); | |||
} | |||
/** | |||
* setup file system for user | |||
* | |||
* @param string $uid user id | |||
*/ | |||
protected function setupFS($uid) { | |||
\OC_Util::setupFS($uid); | |||
} | |||
} |
@@ -174,6 +174,11 @@ class KeyManager { | |||
* check if a key pair for the master key exists, if not we create one | |||
*/ | |||
public function validateMasterKey() { | |||
if ($this->util->isMasterKeyEnabled() === false) { | |||
return; | |||
} | |||
$masterKey = $this->getPublicMasterKey(); | |||
if (empty($masterKey)) { | |||
$keyPair = $this->crypt->createKeyPair(); | |||
@@ -334,7 +339,7 @@ class KeyManager { | |||
/** | |||
* Decrypt private key and store it | |||
* | |||
* @param string $uid userid | |||
* @param string $uid user id | |||
* @param string $passPhrase users password | |||
* @return boolean | |||
*/ | |||
@@ -342,7 +347,6 @@ class KeyManager { | |||
$this->session->setStatus(Session::INIT_EXECUTED); | |||
try { | |||
if($this->util->isMasterKeyEnabled()) { | |||
$uid = $this->getMasterKeyId(); |
@@ -66,29 +66,23 @@ class Setup { | |||
} | |||
/** | |||
* @param string $uid userid | |||
* @param string $uid user id | |||
* @param string $password user password | |||
* @return bool | |||
*/ | |||
public function setupUser($uid, $password) { | |||
return $this->setupServerSide($uid, $password); | |||
if (!$this->keyManager->userHasKeys($uid)) { | |||
return $this->keyManager->storeKeyPair($uid, $password, | |||
$this->crypt->createKeyPair()); | |||
} | |||
return true; | |||
} | |||
/** | |||
* check if user has a key pair, if not we create one | |||
* | |||
* @param string $uid userid | |||
* @param string $password user password | |||
* @return bool | |||
* make sure that all system keys exists | |||
*/ | |||
public function setupServerSide($uid, $password) { | |||
public function setupSystem() { | |||
$this->keyManager->validateShareKey(); | |||
$this->keyManager->validateMasterKey(); | |||
// Check if user already has keys | |||
if (!$this->keyManager->userHasKeys($uid)) { | |||
return $this->keyManager->storeKeyPair($uid, $password, | |||
$this->crypt->createKeyPair()); | |||
} | |||
return true; | |||
} | |||
} |
@@ -71,7 +71,7 @@ class UserHooksTest extends TestCase { | |||
private $params = ['uid' => 'testUser', 'password' => 'password']; | |||
public function testLogin() { | |||
$this->userSetupMock->expects($this->exactly(2)) | |||
$this->userSetupMock->expects($this->once()) | |||
->method('setupUser') | |||
->willReturnOnConsecutiveCalls(true, false); | |||
@@ -80,7 +80,6 @@ class UserHooksTest extends TestCase { | |||
->with('testUser', 'password'); | |||
$this->assertNull($this->instance->login($this->params)); | |||
$this->assertFalse($this->instance->login($this->params)); | |||
} | |||
public function testLogout() { | |||
@@ -256,7 +255,7 @@ class UserHooksTest extends TestCase { | |||
->with('testUser'); | |||
$this->userSetupMock->expects($this->once()) | |||
->method('setupServerSide') | |||
->method('setupUser') | |||
->with('testUser', 'password'); | |||
$this->assertNull($this->instance->postPasswordReset($this->params)); | |||
@@ -312,16 +311,22 @@ class UserHooksTest extends TestCase { | |||
$this->sessionMock = $sessionMock; | |||
$this->recoveryMock = $recoveryMock; | |||
$this->utilMock = $utilMock; | |||
$this->instance = new UserHooks($this->keyManagerMock, | |||
$this->userManagerMock, | |||
$this->loggerMock, | |||
$this->userSetupMock, | |||
$this->userSessionMock, | |||
$this->utilMock, | |||
$this->sessionMock, | |||
$this->cryptMock, | |||
$this->recoveryMock | |||
); | |||
$this->utilMock->expects($this->any())->method('isMasterKeyEnabled')->willReturn(false); | |||
$this->instance = $this->getMockBuilder('OCA\Encryption\Hooks\UserHooks') | |||
->setConstructorArgs( | |||
[ | |||
$this->keyManagerMock, | |||
$this->userManagerMock, | |||
$this->loggerMock, | |||
$this->userSetupMock, | |||
$this->userSessionMock, | |||
$this->utilMock, | |||
$this->sessionMock, | |||
$this->cryptMock, | |||
$this->recoveryMock | |||
] | |||
)->setMethods(['setupFS'])->getMock(); | |||
} | |||
@@ -41,26 +41,6 @@ class SetupTest extends TestCase { | |||
*/ | |||
private $instance; | |||
public function testSetupServerSide() { | |||
$this->keyManagerMock->expects($this->exactly(2))->method('validateShareKey'); | |||
$this->keyManagerMock->expects($this->exactly(2))->method('validateMasterKey'); | |||
$this->keyManagerMock->expects($this->exactly(2)) | |||
->method('userHasKeys') | |||
->with('admin') | |||
->willReturnOnConsecutiveCalls(true, false); | |||
$this->assertTrue($this->instance->setupServerSide('admin', | |||
'password')); | |||
$this->keyManagerMock->expects($this->once()) | |||
->method('storeKeyPair') | |||
->with('admin', 'password') | |||
->willReturn(false); | |||
$this->assertFalse($this->instance->setupServerSide('admin', | |||
'password')); | |||
} | |||
protected function setUp() { | |||
parent::setUp(); | |||
$logMock = $this->getMock('OCP\ILogger'); | |||
@@ -81,4 +61,43 @@ class SetupTest extends TestCase { | |||
$this->keyManagerMock); | |||
} | |||
public function testSetupSystem() { | |||
$this->keyManagerMock->expects($this->once())->method('validateShareKey'); | |||
$this->keyManagerMock->expects($this->once())->method('validateMasterKey'); | |||
$this->instance->setupSystem(); | |||
} | |||
/** | |||
* @dataProvider dataTestSetupUser | |||
* | |||
* @param bool $hasKeys | |||
* @param bool $expected | |||
*/ | |||
public function testSetupUser($hasKeys, $expected) { | |||
$this->keyManagerMock->expects($this->once())->method('userHasKeys') | |||
->with('uid')->willReturn($hasKeys); | |||
if ($hasKeys) { | |||
$this->keyManagerMock->expects($this->never())->method('storeKeyPair'); | |||
} else { | |||
$this->cryptMock->expects($this->once())->method('createKeyPair')->willReturn('keyPair'); | |||
$this->keyManagerMock->expects($this->once())->method('storeKeyPair') | |||
->with('uid', 'password', 'keyPair')->willReturn(true); | |||
} | |||
$this->assertSame($expected, | |||
$this->instance->setupUser('uid', 'password') | |||
); | |||
} | |||
public function dataTestSetupUser() { | |||
return [ | |||
[true, true], | |||
[false, true] | |||
]; | |||
} | |||
} |
@@ -63,7 +63,7 @@ trait EncryptionTrait { | |||
$keyManager = $container->query('KeyManager'); | |||
/** @var Setup $userSetup */ | |||
$userSetup = $container->query('UserSetup'); | |||
$userSetup->setupServerSide($name, $password); | |||
$userSetup->setupUser($name, $password); | |||
$keyManager->init($name, $password); | |||
} | |||