From 2e3bfdb12c5789e1e384777a7906c2c6a6ecef56 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 31 May 2013 13:58:58 +0200 Subject: [PATCH 01/24] check if the decrypted private key is valid on login and on read/write files --- apps/files_encryption/hooks/hooks.php | 17 ++++++++++++++++- apps/files_encryption/lib/stream.php | 21 +++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index eb9a2600d7..639d576915 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -57,6 +57,21 @@ class Hooks { $privateKey = Crypt::symmetricDecryptFileContent($encryptedKey, $params['password']); + // check if this a valid private key + $res = openssl_pkey_get_private($privateKey); + if(is_resource($res)) { + $sslInfo = openssl_pkey_get_details($res); + if(!isset($sslInfo['key'])) { + $privateKey = null; + } + } else { + $privateKey = null; + } + + if($privateKey === null) { + \OCP\Util::writeLog('Encryption library', 'Private key for user "' . $params['uid'] . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR); + } + $session = new \OCA\Encryption\Session($view); $session->setPrivateKey($privateKey, $params['uid']); @@ -143,7 +158,7 @@ class Hooks { public static function setPassphrase($params) { // Only attempt to change passphrase if server-side encryption - // is in use (client-side encryption does not have access to + // is in use (client-side encryption does not have access to // the necessary keys) if (Crypt::mode() === 'server') { diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 072c528664..56322c100b 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -118,7 +118,7 @@ class Stream { if (!is_resource($this->handle)) { - \OCP\Util::writeLog('files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR); + \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR); } else { @@ -156,7 +156,7 @@ class Stream { // $count will always be 8192 https://bugs.php.net/bug.php?id=21641 // This makes this function a lot simpler, but will break this class if the above 'bug' gets 'fixed' - \OCP\Util::writeLog('files_encryption', 'PHP "bug" 21641 no longer holds, decryption system requires refactoring', \OCP\Util::FATAL); + \OCP\Util::writeLog('Encryption library', 'PHP "bug" 21641 no longer holds, decryption system requires refactoring', \OCP\Util::FATAL); die(); @@ -165,7 +165,7 @@ class Stream { // Get the data from the file handle $data = fread($this->handle, 8192); - $result = ''; + $result = null; if (strlen($data)) { @@ -175,10 +175,11 @@ class Stream { throw new \Exception( 'Encryption key not found for "' . $this->rawPath . '" during attempted read via stream'); - } + } else { - // Decrypt data - $result = Crypt::symmetricDecryptFileContent($data, $this->plainKey); + // Decrypt data + $result = Crypt::symmetricDecryptFileContent($data, $this->plainKey); + } } @@ -232,6 +233,14 @@ class Stream { $privateKey = $session->getPrivateKey($this->userId); + // if there is no valid private key return false + if($privateKey === false) { + + \OCP\Util::writeLog('Encryption library', 'Private key for user "' . $this->userId . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR); + + return false; + } + $shareKey = Keymanager::getShareKey($this->rootView, $this->userId, $this->relPath); $this->plainKey = Crypt::multiKeyDecrypt($this->encKeyfile, $shareKey, $privateKey); From e9d1ea712c5986f427fb8fbbcc934d119a069f5c Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 31 May 2013 15:57:18 +0200 Subject: [PATCH 02/24] allow the user to login but do not allow upload and show error message on the web --- apps/files_encryption/appinfo/app.php | 3 ++- apps/files_encryption/hooks/hooks.php | 6 +++--- apps/files_encryption/lib/stream.php | 24 +++++++++++++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index d9bb4d5e74..c9e3de5691 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -28,9 +28,10 @@ if (OCP\User::isLoggedIn()) { $view = new OC_FilesystemView('/'); $session = new \OCA\Encryption\Session($view); + $user = \OCP\USER::getUser(); // check if user has a private key if ( - !$session->getPrivateKey(\OCP\USER::getUser()) + !$view->file_exists('/' . $user . '/files_encryption/' . $user . '.private.key') && OCA\Encryption\Crypt::mode() === 'server' ) { diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 639d576915..c52d739eaa 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -62,13 +62,13 @@ class Hooks { if(is_resource($res)) { $sslInfo = openssl_pkey_get_details($res); if(!isset($sslInfo['key'])) { - $privateKey = null; + $privateKey = false; } } else { - $privateKey = null; + $privateKey = false; } - if($privateKey === null) { + if($privateKey === false) { \OCP\Util::writeLog('Encryption library', 'Private key for user "' . $params['uid'] . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR); } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 56322c100b..a5ebe8ef91 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -236,7 +236,11 @@ class Stream { // if there is no valid private key return false if($privateKey === false) { - \OCP\Util::writeLog('Encryption library', 'Private key for user "' . $this->userId . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR); + if(\OC_Util::isCallRegistered()) { + $l = \OC_L10N::get('core'); + \OCP\JSON::error(array('data' => array('message' => $l->t('Private key is not valid! Maybe the user password was changed from outside if so please change it back to gain access')))); + throw new \Exception('Private key for user "' . $this->userId . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); + } return false; } @@ -433,6 +437,22 @@ class Stream { $this->flush(); + $view = new \OC_FilesystemView('/'); + $session = new \OCA\Encryption\Session( $this->rootView ); + $privateKey = $session->getPrivateKey($this->userId); + + // if there is no valid private key return false + if($privateKey === false) { + + if(\OC_Util::isCallRegistered()) { + $l = \OC_L10N::get('core'); + \OCP\JSON::error(array('data' => array('message' => $l->t('Private key is not valid! Maybe the user password was changed from outside if so please change it back to gain access')))); + throw new \Exception('Private key for user "' . $this->userId . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); + } + + return false; + } + if ( $this->meta['mode'] !== 'r' and $this->meta['mode'] !== 'rb' @@ -459,8 +479,6 @@ class Stream { // Encrypt enc key for all sharing users $this->encKeyfiles = Crypt::multiKeyEncrypt($this->plainKey, $publicKeys); - $view = new \OC_FilesystemView('/'); - // Save the new encrypted file key Keymanager::setFileKey($this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data']); From a134ffcf2cce4dcd2c41ccd49a5b6306260bb0f3 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 31 May 2013 16:52:33 +0200 Subject: [PATCH 03/24] code optimized and cleaned up unused vars --- apps/files_encryption/lib/stream.php | 70 +++++++++++++++++++--------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index a5ebe8ef91..dee5a7cccc 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -56,18 +56,21 @@ class Stream { private $relPath; // rel path to users file dir private $userId; private $handle; // Resource returned by fopen - private $path; - private $readBuffer; // For streams that dont support seeking private $meta = array(); // Header / meta for source stream - private $count; private $writeCache; private $size; private $unencryptedSize; private $publicKey; - private $keyfile; private $encKeyfile; - private static $view; // a fsview object set to user dir + /** + * @var \OC\Files\View + */ private $rootView; // a fsview object set to '/' + /** + * @var \OCA\Encryption\Session + */ + private $session; + private $privateKey; /** * @param $path @@ -82,6 +85,10 @@ class Stream { $this->rootView = new \OC_FilesystemView('/'); } + $this->session = new \OCA\Encryption\Session($this->rootView); + + $this->privateKey = $this->session->getPrivateKey($this->userId); + $util = new Util($this->rootView, \OCP\USER::getUser()); $this->userId = $util->getUserId(); @@ -229,17 +236,14 @@ class Stream { // If a keyfile already exists if ($this->encKeyfile) { - $session = new \OCA\Encryption\Session( $this->rootView ); - - $privateKey = $session->getPrivateKey($this->userId); - // if there is no valid private key return false - if($privateKey === false) { + if ($this->privateKey === false) { - if(\OC_Util::isCallRegistered()) { + if (\OC_Util::isCallRegistered()) { $l = \OC_L10N::get('core'); \OCP\JSON::error(array('data' => array('message' => $l->t('Private key is not valid! Maybe the user password was changed from outside if so please change it back to gain access')))); - throw new \Exception('Private key for user "' . $this->userId . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); + throw new \Exception('Private key for user "' . $this->userId + . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); } return false; @@ -247,7 +251,7 @@ class Stream { $shareKey = Keymanager::getShareKey($this->rootView, $this->userId, $this->relPath); - $this->plainKey = Crypt::multiKeyDecrypt($this->encKeyfile, $shareKey, $privateKey); + $this->plainKey = Crypt::multiKeyDecrypt($this->encKeyfile, $shareKey, $this->privateKey); return true; @@ -270,6 +274,12 @@ class Stream { */ public function stream_write($data) { + // if there is no valid private key return false + if ($this->privateKey === false) { + $this->size = 0; + return strlen($data); + } + // Disable the file proxies so that encryption is not // automatically attempted when the file is written to disk - // we are handling that separately here and we don't want to @@ -437,19 +447,33 @@ class Stream { $this->flush(); - $view = new \OC_FilesystemView('/'); - $session = new \OCA\Encryption\Session( $this->rootView ); - $privateKey = $session->getPrivateKey($this->userId); - // if there is no valid private key return false - if($privateKey === false) { + if ($this->privateKey === false) { - if(\OC_Util::isCallRegistered()) { + if (\OC_Util::isCallRegistered()) { $l = \OC_L10N::get('core'); \OCP\JSON::error(array('data' => array('message' => $l->t('Private key is not valid! Maybe the user password was changed from outside if so please change it back to gain access')))); - throw new \Exception('Private key for user "' . $this->userId . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); + + // cleanup + if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb') { + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + if ($this->rootView->file_exists($this->rawPath) && $this->size === 0) { + $this->rootView->unlink($this->rawPath); + } + + // Re-enable proxy - our work is done + \OC_FileProxy::$enabled = $proxyStatus; + } + + throw new \Exception('Private key for user "' . $this->userId + . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); } + return false; } @@ -483,10 +507,10 @@ class Stream { Keymanager::setFileKey($this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data']); // Save the sharekeys - Keymanager::setShareKeys($view, $this->relPath, $this->encKeyfiles['keys']); + Keymanager::setShareKeys($this->rootView, $this->relPath, $this->encKeyfiles['keys']); // get file info - $fileInfo = $view->getFileInfo($this->rawPath); + $fileInfo = $this->rootView->getFileInfo($this->rawPath); if (!is_array($fileInfo)) { $fileInfo = array(); } @@ -500,7 +524,7 @@ class Stream { $fileInfo['unencrypted_size'] = $this->unencryptedSize; // set fileinfo - $view->putFileInfo($this->rawPath, $fileInfo); + $this->rootView->putFileInfo($this->rawPath, $fileInfo); } return fclose($this->handle); From 471d2b732c504d7231aa7f343f5cda8a701fa447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 3 Jun 2013 14:19:31 +0200 Subject: [PATCH 04/24] introduce decryptPrivateKey() method which also checks if the result is a valid private key to avoid additional checks on various places --- .../ajax/changeRecoveryPassword.php | 22 +++++++-------- apps/files_encryption/hooks/hooks.php | 13 +-------- apps/files_encryption/lib/crypt.php | 28 +++++++++++++++++++ apps/files_encryption/lib/helper.php | 8 +----- apps/files_encryption/lib/session.php | 2 +- apps/files_encryption/lib/util.php | 16 +++++------ 6 files changed, 49 insertions(+), 40 deletions(-) diff --git a/apps/files_encryption/ajax/changeRecoveryPassword.php b/apps/files_encryption/ajax/changeRecoveryPassword.php index b0594f967b..366f634a51 100644 --- a/apps/files_encryption/ajax/changeRecoveryPassword.php +++ b/apps/files_encryption/ajax/changeRecoveryPassword.php @@ -22,28 +22,28 @@ $return = false; $oldPassword = $_POST['oldPassword']; $newPassword = $_POST['newPassword']; +$view = new \OC\Files\View('/'); $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); -$result = $util->checkRecoveryPassword($oldPassword); +$proxyStatus = \OC_FileProxy::$enabled; +\OC_FileProxy::$enabled = false; -if ($result) { - $keyId = $util->getRecoveryKeyId(); - $keyPath = '/owncloud_private_key/' . $keyId . '.private.key'; - $view = new \OC\Files\View('/'); +$keyId = $util->getRecoveryKeyId(); +$keyPath = '/owncloud_private_key/' . $keyId . '.private.key'; - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; +$encryptedRecoveryKey = $view->file_get_contents($keyPath); +$decryptedRecoveryKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedRecoveryKey, $oldPassword); + +if ($decryptedRecoveryKey) { - $encryptedRecoveryKey = $view->file_get_contents($keyPath); - $decryptedRecoveryKey = \OCA\Encryption\Crypt::symmetricDecryptFileContent($encryptedRecoveryKey, $oldPassword); $encryptedRecoveryKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($decryptedRecoveryKey, $newPassword); $view->file_put_contents($keyPath, $encryptedRecoveryKey); - \OC_FileProxy::$enabled = $proxyStatus; - $return = true; } +\OC_FileProxy::$enabled = $proxyStatus; + // success or failure if ($return) { \OCP\JSON::success(array('data' => array('message' => $l->t('Password successfully changed.')))); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index c52d739eaa..47e240769b 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -55,18 +55,7 @@ class Hooks { $encryptedKey = Keymanager::getPrivateKey($view, $params['uid']); - $privateKey = Crypt::symmetricDecryptFileContent($encryptedKey, $params['password']); - - // check if this a valid private key - $res = openssl_pkey_get_private($privateKey); - if(is_resource($res)) { - $sslInfo = openssl_pkey_get_details($res); - if(!isset($sslInfo['key'])) { - $privateKey = false; - } - } else { - $privateKey = false; - } + $privateKey = Crypt::decryptPrivateKey($encryptedKey, $params['password']); if($privateKey === false) { \OCP\Util::writeLog('Encryption library', 'Private key for user "' . $params['uid'] . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR); diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index ddeb3590f6..8c96e53641 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -351,6 +351,34 @@ class Crypt { } + /** + * @brief Decrypt private key and check if the result is a valid keyfile + * @param string $encryptedKey encrypted keyfile + * @param string $passphrase to decrypt keyfile + * @returns encrypted private key or false + * + * This function decrypts a file + */ + public static function decryptPrivateKey($encryptedKey, $passphrase) { + + $plainKey = self::symmetricDecryptFileContent($encryptedKey, $passphrase); + + // check if this a valid private key + $res = openssl_pkey_get_private($plainKey); + if(is_resource($res)) { + $sslInfo = openssl_pkey_get_details($res); + if(!isset($sslInfo['key'])) { + $plainKey = false; + } + } else { + $plainKey = false; + } + + return $plainKey; + + } + + /** * @brief Creates symmetric keyfile content using a generated key * @param string $plainContent content to be encrypted diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index e078ab3554..42871a4a95 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -93,6 +93,7 @@ class Helper { * @return bool */ public static function adminEnableRecovery($recoveryKeyId, $recoveryPassword) { + $view = new \OC\Files\View('/'); if ($recoveryKeyId === null) { @@ -127,13 +128,6 @@ class Helper { // Save private key $view->file_put_contents('/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey); - // create control file which let us check later on if the entered password was correct. - $encryptedControlData = \OCA\Encryption\Crypt::keyEncrypt("ownCloud", $keypair['publicKey']); - if (!$view->is_dir('/control-file')) { - $view->mkdir('/control-file'); - } - $view->file_put_contents('/control-file/controlfile.enc', $encryptedControlData); - \OC_FileProxy::$enabled = true; // Set recoveryAdmin as enabled diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index bff1737554..9b0ca224c8 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -89,7 +89,7 @@ class Session { \OC_FileProxy::$enabled = false; $encryptedKey = $this->view->file_get_contents( '/owncloud_private_key/' . $publicShareKeyId . '.private.key' ); - $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, '' ); + $privateKey = Crypt::decryptPrivateKey($encryptedKey, ''); $this->setPublicSharePrivateKey( $privateKey ); \OC_FileProxy::$enabled = $proxyStatus; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 04bd4dc8ac..6923b81b92 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -1372,26 +1372,24 @@ class Util { */ public function checkRecoveryPassword($password) { + $result = false; $pathKey = '/owncloud_private_key/' . $this->recoveryKeyId . ".private.key"; - $pathControlData = '/control-file/controlfile.enc'; $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $recoveryKey = $this->view->file_get_contents($pathKey); - $decryptedRecoveryKey = Crypt::symmetricDecryptFileContent($recoveryKey, $password); + $decryptedRecoveryKey = Crypt::decryptPrivateKey($recoveryKey, $password); - $controlData = $this->view->file_get_contents($pathControlData); - $decryptedControlData = Crypt::keyDecrypt($controlData, $decryptedRecoveryKey); + if ($decryptedRecoveryKey) { + $result = true; + } \OC_FileProxy::$enabled = $proxyStatus; - if ($decryptedControlData === 'ownCloud') { - return true; - } - return false; + return $result; } /** @@ -1520,7 +1518,7 @@ class Util { $encryptedKey = $this->view->file_get_contents( '/owncloud_private_key/' . $this->recoveryKeyId . '.private.key'); - $privateKey = Crypt::symmetricDecryptFileContent($encryptedKey, $recoveryPassword); + $privateKey = Crypt::decryptPrivateKey($encryptedKey, $recoveryPassword); \OC_FileProxy::$enabled = $proxyStatus; From 42f66af5a306ea959c7be3eb84ff93b4faf6cb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 3 Jun 2013 14:21:30 +0200 Subject: [PATCH 05/24] control files are no longer needed, remove them from the tests --- apps/files_encryption/tests/share.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 6d92881ceb..28f0de4941 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -646,9 +646,6 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123'); $recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); - // check if control file created - $this->assertTrue($this->view->file_exists('/control-file/controlfile.enc')); - // login as admin \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); @@ -748,9 +745,6 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123'); $recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); - // check if control file created - $this->assertTrue($this->view->file_exists('/control-file/controlfile.enc')); - // login as user1 \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); From b02f4dc62c797f11818d245015e76b49636afbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 3 Jun 2013 15:26:58 +0200 Subject: [PATCH 06/24] $session->setPrivateKey expects only one parameter --- apps/files_encryption/hooks/hooks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 47e240769b..5271b51202 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -63,7 +63,7 @@ class Hooks { $session = new \OCA\Encryption\Session($view); - $session->setPrivateKey($privateKey, $params['uid']); + $session->setPrivateKey($privateKey); // Check if first-run file migration has already been performed $migrationCompleted = $util->getMigrationStatus(); From b5820af3cc713bc8c373d28bb6b6ff69a70545b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 3 Jun 2013 15:27:31 +0200 Subject: [PATCH 07/24] let user update private key password in case it was changed from outside, e.g. external auth back-ends --- .../ajax/updatePrivateKeyPassword.php | 54 +++++++++++++++++++ apps/files_encryption/js/settings-personal.js | 30 +++++++++++ apps/files_encryption/settings-personal.php | 4 ++ .../templates/settings-personal.php | 30 +++++++++++ 4 files changed, 118 insertions(+) create mode 100644 apps/files_encryption/ajax/updatePrivateKeyPassword.php diff --git a/apps/files_encryption/ajax/updatePrivateKeyPassword.php b/apps/files_encryption/ajax/updatePrivateKeyPassword.php new file mode 100644 index 0000000000..e0b3d55d8b --- /dev/null +++ b/apps/files_encryption/ajax/updatePrivateKeyPassword.php @@ -0,0 +1,54 @@ + + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + * + * @brief Script to change recovery key password + * + */ + +use OCA\Encryption; + +\OCP\JSON::checkLoggedIn(); +\OCP\JSON::checkAppEnabled('files_encryption'); +\OCP\JSON::callCheck(); + +$l = OC_L10N::get('core'); + +$return = false; + +$oldPassword = $_POST['oldPassword']; +$newPassword = $_POST['newPassword']; + +$view = new \OC\Files\View('/'); +$session = new \OCA\Encryption\Session($view); +$user = \OCP\User::getUser(); + +$proxyStatus = \OC_FileProxy::$enabled; +\OC_FileProxy::$enabled = false; + +$keyPath = '/' . $user . '/files_encryption/'.$user.'.private.key'; + +$encryptedKey = $view->file_get_contents($keyPath); +$decryptedKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, $oldPassword); + +if ($decryptedKey) { + + $encryptedKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($decryptedKey, $newPassword); + $view->file_put_contents($keyPath, $encryptedKey); + + $session->getPrivateKey($decryptedKey); + + $return = true; +} + +\OC_FileProxy::$enabled = $proxyStatus; + +// success or failure +if ($return) { + \OCP\JSON::success(array('data' => array('message' => $l->t('Private key password successfully updated.')))); +} else { + \OCP\JSON::error(array('data' => array('message' => $l->t('Could not update the private key password. Maybe the old password was not correct.')))); +} \ No newline at end of file diff --git a/apps/files_encryption/js/settings-personal.js b/apps/files_encryption/js/settings-personal.js index 312b672ad4..46105176c2 100644 --- a/apps/files_encryption/js/settings-personal.js +++ b/apps/files_encryption/js/settings-personal.js @@ -57,4 +57,34 @@ $(document).ready(function(){ } ); + + // update private key password + + $('input:password[name="changePrivateKeyPassword"]').keyup(function(event) { + var oldPrivateKeyPassword = $('input:password[id="oldPrivateKeyPassword"]').val(); + var newPrivateKeyPassword = $('input:password[id="newPrivateKeyPassword"]').val(); + if (newPrivateKeyPassword != '' && oldPrivateKeyPassword != '' ) { + $('button:button[name="submitChangePrivateKeyPassword"]').removeAttr("disabled"); + } else { + $('button:button[name="submitChangePrivateKeyPassword"]').attr("disabled", "true"); + } + }); + + $('button:button[name="submitChangePrivateKeyPassword"]').click(function() { + var oldPrivateKeyPassword = $('input:password[id="oldPrivateKeyPassword"]').val(); + var newPrivateKeyPassword = $('input:password[id="newPrivateKeyPassword"]').val(); + OC.msg.startSaving('#encryption .msg'); + $.post( + OC.filePath( 'files_encryption', 'ajax', 'updatePrivateKeyPassword.php' ) + , { oldPassword: oldPrivateKeyPassword, newPassword: newPrivateKeyPassword } + , function( data ) { + if (data.status == "error") { + OC.msg.finishedSaving('#encryption .msg', data); + } else { + OC.msg.finishedSaving('#encryption .msg', data); + } + } + ); + }); + }); \ No newline at end of file diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php index 3e96565949..d23a4cfdde 100644 --- a/apps/files_encryption/settings-personal.php +++ b/apps/files_encryption/settings-personal.php @@ -14,6 +14,9 @@ $tmpl = new OCP\Template('files_encryption', 'settings-personal'); $user = \OCP\USER::getUser(); $view = new \OC_FilesystemView('/'); $util = new \OCA\Encryption\Util($view, $user); +$session = new \OCA\Encryption\Session($view); + +$privateKeySet = ($session->getPrivateKey() !== false) ? true : false; $recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'); $recoveryEnabledForUser = $util->recoveryEnabledForUser(); @@ -23,6 +26,7 @@ $recoveryEnabledForUser = $util->recoveryEnabledForUser(); $tmpl->assign('recoveryEnabled', $recoveryAdminEnabled); $tmpl->assign('recoveryEnabledForUser', $recoveryEnabledForUser); +$tmpl->assign("privateKeySet" , $privateKeySet); return $tmpl->fetchPage(); diff --git a/apps/files_encryption/templates/settings-personal.php b/apps/files_encryption/templates/settings-personal.php index 04d6e79179..bacdc13337 100644 --- a/apps/files_encryption/templates/settings-personal.php +++ b/apps/files_encryption/templates/settings-personal.php @@ -3,6 +3,35 @@ t( 'Encryption' ) ); ?> + + +

+ +
+ t( "Set your old private key password to your current log-in password." ) ); ?> +
+ + +
+ + +
+ + +

+ + +

@@ -28,6 +57,7 @@

t( 'Could not update file recovery' ) ); ?>

+
From 35c91ff9010f84aa204030f4bb60f36dca1cb664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 3 Jun 2013 17:34:43 +0200 Subject: [PATCH 08/24] added test for decryptPrivateKey() --- apps/files_encryption/tests/crypt.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 32156eea27..74f91e9b03 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -226,6 +226,24 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { } + function testDecryptPrivateKey() { + + $keypair = Encryption\Crypt::createKeypair(); + + // test successful decrypt + $crypted = Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], 'hat'); + + $decrypted = Encryption\Crypt::decryptPrivateKey($crypted, 'hat'); + + $this->assertEquals($keypair['privateKey'], $decrypted); + + //test private key decrypt with wrong password + $wrongPasswd = Encryption\Crypt::decryptPrivateKey($crypted, 'hat2'); + + $this->assertEquals(false, $wrongPasswd); + + } + function testSymmetricEncryptFileContent() { # TODO: search in keyfile for actual content as IV will ensure this test always passes From 1e601cd6f1a4be0f3736467e08c6de8603b6aad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 3 Jun 2013 17:43:06 +0200 Subject: [PATCH 09/24] use generated private key fro m setUp() --- apps/files_encryption/tests/crypt.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 74f91e9b03..bb84ff2690 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -228,14 +228,12 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { function testDecryptPrivateKey() { - $keypair = Encryption\Crypt::createKeypair(); - // test successful decrypt - $crypted = Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], 'hat'); + $crypted = Encryption\Crypt::symmetricEncryptFileContent($this->genPrivateKey, 'hat'); $decrypted = Encryption\Crypt::decryptPrivateKey($crypted, 'hat'); - $this->assertEquals($keypair['privateKey'], $decrypted); + $this->assertEquals($this->genPrivateKey, $decrypted); //test private key decrypt with wrong password $wrongPasswd = Encryption\Crypt::decryptPrivateKey($crypted, 'hat2'); From dc8bcf0688c80220a864b5829ecefbd2c0d70ea4 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 3 Jun 2013 18:42:13 +0200 Subject: [PATCH 10/24] reformat code --- .../ajax/updatePrivateKeyPassword.php | 2 +- apps/files_encryption/hooks/hooks.php | 11 +-- apps/files_encryption/lib/crypt.php | 4 +- apps/files_encryption/lib/helper.php | 2 +- apps/files_encryption/lib/session.php | 13 ++-- apps/files_encryption/lib/util.php | 45 +++++++----- apps/files_encryption/settings-personal.php | 2 +- .../templates/settings-admin.php | 72 ++++++++++--------- apps/files_encryption/tests/crypt.php | 3 +- apps/files_encryption/tests/share.php | 3 +- 10 files changed, 83 insertions(+), 74 deletions(-) diff --git a/apps/files_encryption/ajax/updatePrivateKeyPassword.php b/apps/files_encryption/ajax/updatePrivateKeyPassword.php index e0b3d55d8b..49f97dd323 100644 --- a/apps/files_encryption/ajax/updatePrivateKeyPassword.php +++ b/apps/files_encryption/ajax/updatePrivateKeyPassword.php @@ -29,7 +29,7 @@ $user = \OCP\User::getUser(); $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; -$keyPath = '/' . $user . '/files_encryption/'.$user.'.private.key'; +$keyPath = '/' . $user . '/files_encryption/' . $user . '.private.key'; $encryptedKey = $view->file_get_contents($keyPath); $decryptedKey = \OCA\Encryption\Crypt::decryptPrivateKey($encryptedKey, $oldPassword); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 5271b51202..cfe9e9d2a3 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -57,8 +57,9 @@ class Hooks { $privateKey = Crypt::decryptPrivateKey($encryptedKey, $params['password']); - if($privateKey === false) { - \OCP\Util::writeLog('Encryption library', 'Private key for user "' . $params['uid'] . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR); + if ($privateKey === false) { + \OCP\Util::writeLog('Encryption library', 'Private key for user "' . $params['uid'] + . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access', \OCP\Util::ERROR); } $session = new \OCA\Encryption\Session($view); @@ -332,7 +333,7 @@ class Hooks { $sharingEnabled = \OCP\Share::isEnabled(); // get the path including mount point only if not a shared folder - if(strncmp($path, '/Shared' , strlen('/Shared') !== 0)) { + if (strncmp($path, '/Shared', strlen('/Shared') !== 0)) { // get path including the the storage mount point $path = $util->getPathWithMountPoint($params['itemSource']); } @@ -409,14 +410,14 @@ class Hooks { } // get the path including mount point only if not a shared folder - if(strncmp($path, '/Shared' , strlen('/Shared') !== 0)) { + if (strncmp($path, '/Shared', strlen('/Shared') !== 0)) { // get path including the the storage mount point $path = $util->getPathWithMountPoint($params['itemSource']); } // if we unshare a folder we need a list of all (sub-)files if ($params['itemType'] === 'folder') { - $allFiles = $util->getAllFiles( $path ); + $allFiles = $util->getAllFiles($path); } else { $allFiles = array($path); } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 8c96e53641..ecbec2e8b2 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -365,9 +365,9 @@ class Crypt { // check if this a valid private key $res = openssl_pkey_get_private($plainKey); - if(is_resource($res)) { + if (is_resource($res)) { $sslInfo = openssl_pkey_get_details($res); - if(!isset($sslInfo['key'])) { + if (!isset($sslInfo['key'])) { $plainKey = false; } } else { diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 42871a4a95..3e581a6ee3 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -73,7 +73,7 @@ class Helper { if (!$util->ready()) { \OCP\Util::writeLog('Encryption library', 'User account "' . $util->getUserId() - . '" is not ready for encryption; configuration started', \OCP\Util::DEBUG); + . '" is not ready for encryption; configuration started', \OCP\Util::DEBUG); if (!$util->setupServerSide($password)) { return false; diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 9b0ca224c8..1911386cd1 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -88,9 +88,10 @@ class Session { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - $encryptedKey = $this->view->file_get_contents( '/owncloud_private_key/' . $publicShareKeyId . '.private.key' ); + $encryptedKey = $this->view->file_get_contents( + '/owncloud_private_key/' . $publicShareKeyId . '.private.key'); $privateKey = Crypt::decryptPrivateKey($encryptedKey, ''); - $this->setPublicSharePrivateKey( $privateKey ); + $this->setPublicSharePrivateKey($privateKey); \OC_FileProxy::$enabled = $proxyStatus; } @@ -121,7 +122,7 @@ class Session { if (\OCA\Encryption\Helper::isPublicAccess()) { return $this->getPublicSharePrivateKey(); } else { - if (!is_null( \OC::$session->get('privateKey') )) { + if (!is_null(\OC::$session->get('privateKey'))) { return \OC::$session->get('privateKey'); } else { return false; @@ -136,7 +137,7 @@ class Session { */ public function setPublicSharePrivateKey($privateKey) { - \OC::$session->set('publicSharePrivateKey', $privateKey); + \OC::$session->set('publicSharePrivateKey', $privateKey); return true; @@ -149,7 +150,7 @@ class Session { */ public function getPublicSharePrivateKey() { - if (!is_null( \OC::$session->get('publicSharePrivateKey') )) { + if (!is_null(\OC::$session->get('publicSharePrivateKey'))) { return \OC::$session->get('publicSharePrivateKey'); } else { return false; @@ -176,7 +177,7 @@ class Session { */ public function getLegacyKey() { - if ( !is_null( \OC::$session->get('legacyKey') ) ) { + if (!is_null(\OC::$session->get('legacyKey'))) { return \OC::$session->get('legacyKey'); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 6923b81b92..6446e83222 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -302,7 +302,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if($result->numRows() > 0) { + if ($result->numRows() > 0) { $row = $result->fetchRow(); if (isset($row['recovery_enabled'])) { $recoveryEnabled[] = $row['recovery_enabled']; @@ -442,7 +442,7 @@ class Util { // If the file uses old // encryption system - } elseif ( Crypt::isLegacyEncryptedContent( $data, $relPath ) ) { + } elseif (Crypt::isLegacyEncryptedContent($data, $relPath)) { $found['legacy'][] = array( 'name' => $file, @@ -573,7 +573,9 @@ class Util { // get relative path $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); - if (isset($pathParts[2]) && $pathParts[2] === 'files' && $this->view->file_exists($path) && $this->isEncryptedPath($path)) { + if (isset($pathParts[2]) && $pathParts[2] === 'files' && $this->view->file_exists($path) + && $this->isEncryptedPath($path) + ) { // get the size from filesystem $fullPath = $this->view->getLocalFile($path); @@ -643,7 +645,7 @@ class Util { return $result; } - + /** * @param $path * @return bool @@ -687,28 +689,32 @@ class Util { $relPath = $plainFile['path']; //relative to /data - $rawPath = '/'.$this->userId . '/files/' . $plainFile['path']; + $rawPath = '/' . $this->userId . '/files/' . $plainFile['path']; // Open plain file handle for binary reading - $plainHandle = $this->view->fopen( $rawPath, 'rb' ); + $plainHandle = $this->view->fopen($rawPath, 'rb'); // Open enc file handle for binary writing, with same filename as original plain file - $encHandle = fopen( 'crypt://' . $relPath.'.tmp', 'wb' ); + $encHandle = fopen('crypt://' . $relPath . '.tmp', 'wb'); // Move plain file to a temporary location - $size = stream_copy_to_stream( $plainHandle, $encHandle ); + $size = stream_copy_to_stream($plainHandle, $encHandle); fclose($encHandle); $fakeRoot = $this->view->getRoot(); - $this->view->chroot('/'.$this->userId.'/files'); + $this->view->chroot('/' . $this->userId . '/files'); $this->view->rename($relPath . '.tmp', $relPath); $this->view->chroot($fakeRoot); // Add the file to the cache - \OC\Files\Filesystem::putFileInfo( $relPath, array( 'encrypted' => true, 'size' => $size, 'unencrypted_size' => $size ) ); + \OC\Files\Filesystem::putFileInfo($relPath, array( + 'encrypted' => true, + 'size' => $size, + 'unencrypted_size' => $size + )); } // Encrypt legacy encrypted files @@ -735,7 +741,7 @@ class Util { $publicKeys = Keymanager::getPublicKeys($this->view, $uniqueUserIds); // Recrypt data, generate catfile - $recrypted = Crypt::legacyKeyRecryptKeyfile( $legacyData, $legacyPassphrase, $publicKeys ); + $recrypted = Crypt::legacyKeyRecryptKeyfile($legacyData, $legacyPassphrase, $publicKeys); $rawPath = $legacyFile['path']; $relPath = \OCA\Encryption\Helper::stripUserFilesPath($rawPath); @@ -831,7 +837,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if($result->numRows() > 0) { + if ($result->numRows() > 0) { $row = $result->fetchRow(); $path = substr($row['path'], strlen('files')); } @@ -1102,7 +1108,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if($result->numRows() > 0) { + if ($result->numRows() > 0) { $row = $result->fetchRow(); if (isset($row['migration_status'])) { $migrationStatus[] = $row['migration_status']; @@ -1191,7 +1197,8 @@ class Util { $result = array(); - $content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath($this->userFilesDir . '/' . $dir)); + $content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath( + $this->userFilesDir . '/' . $dir)); // handling for re shared folders $pathSplit = explode('/', $dir); @@ -1252,7 +1259,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if($result->numRows() > 0) { + if ($result->numRows() > 0) { $row = $result->fetchRow(); } } @@ -1278,7 +1285,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if($result->numRows() > 0) { + if ($result->numRows() > 0) { $row = $result->fetchRow(); } } @@ -1303,7 +1310,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if($result->numRows() > 0) { + if ($result->numRows() > 0) { $source = $result->fetchRow(); } } @@ -1324,7 +1331,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if($result->numRows() > 0) { + if ($result->numRows() > 0) { $item = $result->fetchRow(); } } @@ -1534,7 +1541,7 @@ class Util { list($storage, $internalPath) = \OC\Files\Cache\Cache::getById($id); $mount = \OC\Files\Filesystem::getMountByStorageId($storage); $mountPoint = $mount[0]->getMountPoint(); - $path = \OC\Files\Filesystem::normalizePath($mountPoint.'/'.$internalPath); + $path = \OC\Files\Filesystem::normalizePath($mountPoint . '/' . $internalPath); // reformat the path to be relative e.g. /user/files/folder becomes /folder/ $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php index d23a4cfdde..3aa8b39935 100644 --- a/apps/files_encryption/settings-personal.php +++ b/apps/files_encryption/settings-personal.php @@ -26,7 +26,7 @@ $recoveryEnabledForUser = $util->recoveryEnabledForUser(); $tmpl->assign('recoveryEnabled', $recoveryAdminEnabled); $tmpl->assign('recoveryEnabledForUser', $recoveryEnabledForUser); -$tmpl->assign("privateKeySet" , $privateKeySet); +$tmpl->assign('privateKeySet', $privateKeySet); return $tmpl->fetchPage(); diff --git a/apps/files_encryption/templates/settings-admin.php b/apps/files_encryption/templates/settings-admin.php index 18fea1845f..c420b006c4 100644 --- a/apps/files_encryption/templates/settings-admin.php +++ b/apps/files_encryption/templates/settings-admin.php @@ -1,54 +1,56 @@
- +

- t( 'Encryption' )); ?> -
+ t('Encryption')); ?> +

+

- t( "Enable encryption passwords recovery key (allow sharing to recovery key):" )); ?> -
-
- - -
- /> - t( "Enabled" )); ?> -
- - /> - t( "Disabled" )); ?> + t("Enable encryption passwords recovery key (allow sharing to recovery key):")); ?> +
+
+ + +
+ /> + t("Enabled")); ?> +
+ + /> + t("Disabled")); ?>

-

+

+

- t( "Change encryption passwords recovery key:" )); ?> -

- t("Change encryption passwords recovery key:")); ?> +

+ /> - -
- /> + +
+ /> - -
+ /> + +

diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index bb84ff2690..d856e5d59b 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -92,8 +92,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { // reset app files_trashbin if ($this->stateFilesTrashbin) { OC_App::enable('files_trashbin'); - } - else { + } else { OC_App::disable('files_trashbin'); } } diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 28f0de4941..9a0d542c6d 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -111,8 +111,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // reset app files_trashbin if ($this->stateFilesTrashbin) { OC_App::enable('files_trashbin'); - } - else { + } else { OC_App::disable('files_trashbin'); } } From 563f343291fb5d0292c66cb761a053557bfdae47 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 3 Jun 2013 19:06:20 +0200 Subject: [PATCH 11/24] fix password change when files_encryption app is disabled --- settings/ajax/changepassword.php | 52 ++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/settings/ajax/changepassword.php b/settings/ajax/changepassword.php index cb66c57c74..90d213f179 100644 --- a/settings/ajax/changepassword.php +++ b/settings/ajax/changepassword.php @@ -7,38 +7,44 @@ OC_JSON::checkLoggedIn(); // Manually load apps to ensure hooks work correctly (workaround for issue 1503) OC_APP::loadApps(); -$username = isset($_POST["username"]) ? $_POST["username"] : OC_User::getUser(); -$password = isset($_POST["password"]) ? $_POST["password"] : null; -$oldPassword=isset($_POST["oldpassword"])?$_POST["oldpassword"]:''; -$recoveryPassword=isset($_POST["recoveryPassword"])?$_POST["recoveryPassword"]:null; +$username = isset($_POST['username']) ? $_POST['username'] : OC_User::getUser(); +$password = isset($_POST['password']) ? $_POST['password'] : null; +$oldPassword = isset($_POST['oldpassword']) ? $_POST['oldpassword'] : ''; +$recoveryPassword = isset($_POST['recoveryPassword']) ? $_POST['recoveryPassword'] : null; $userstatus = null; -if(OC_User::isAdminUser(OC_User::getUser())) { +if (OC_User::isAdminUser(OC_User::getUser())) { $userstatus = 'admin'; } -if(OC_SubAdmin::isUserAccessible(OC_User::getUser(), $username)) { +if (OC_SubAdmin::isUserAccessible(OC_User::getUser(), $username)) { $userstatus = 'subadmin'; } -if(OC_User::getUser() === $username && OC_User::checkPassword($username, $oldPassword)) { +if (OC_User::getUser() === $username && OC_User::checkPassword($username, $oldPassword)) { $userstatus = 'user'; } -if(is_null($userstatus)) { - OC_JSON::error( array( "data" => array( "message" => "Authentication error" ))); +if (is_null($userstatus)) { + OC_JSON::error(array('data' => array('message' => 'Authentication error'))); exit(); } +if (\OCP\App::isEnabled('files_encryption')) { + $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), $username); + $recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'); + $recoveryEnabledForUser = $util->recoveryEnabledForUser(); -$util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), $username); -$recoveryAdminEnabled = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' ); -$recoveryEnabledForUser = $util->recoveryEnabledForUser(); - -if ($recoveryAdminEnabled && $recoveryEnabledForUser && $recoveryPassword == '') { - OC_JSON::error(array("data" => array( "message" => "Please provide a admin recovery password, otherwise all user data will be lost" ))); -}elseif ( $recoveryPassword && ! $util->checkRecoveryPassword($recoveryPassword) ) { - OC_JSON::error(array("data" => array( "message" => "Wrong admin recovery password. Please check the password and try again." ))); -}elseif(!is_null($password) && OC_User::setPassword( $username, $password, $recoveryPassword )) { - OC_JSON::success(array("data" => array( "username" => $username ))); -} -else{ - OC_JSON::error(array("data" => array( "message" => "Unable to change password" ))); -} + if ($recoveryAdminEnabled && $recoveryEnabledForUser && $recoveryPassword === '') { + OC_JSON::error(array('data' => array('message' => 'Please provide a admin recovery password, otherwise all user data will be lost'))); + } elseif ($recoveryPassword && !$util->checkRecoveryPassword($recoveryPassword)) { + OC_JSON::error(array('data' => array('message' => 'Wrong admin recovery password. Please check the password and try again.'))); + } elseif (!is_null($password) && OC_User::setPassword($username, $password, $recoveryPassword)) { + OC_JSON::success(array('data' => array('username' => $username))); + } else { + OC_JSON::error(array('data' => array('message' => 'Unable to change password'))); + } +} else { + if (!is_null($password) && OC_User::setPassword($username, $password)) { + OC_JSON::success(array('data' => array('username' => $username))); + } else { + OC_JSON::error(array('data' => array('message' => 'Unable to change password'))); + } +} \ No newline at end of file From b46e7323ec6189f16405b8a22b073ca2d18d3bdb Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 3 Jun 2013 19:10:55 +0200 Subject: [PATCH 12/24] fixed typo --- apps/files_encryption/ajax/updatePrivateKeyPassword.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/ajax/updatePrivateKeyPassword.php b/apps/files_encryption/ajax/updatePrivateKeyPassword.php index 49f97dd323..6fd63dae9c 100644 --- a/apps/files_encryption/ajax/updatePrivateKeyPassword.php +++ b/apps/files_encryption/ajax/updatePrivateKeyPassword.php @@ -39,7 +39,7 @@ if ($decryptedKey) { $encryptedKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($decryptedKey, $newPassword); $view->file_put_contents($keyPath, $encryptedKey); - $session->getPrivateKey($decryptedKey); + $session->setPrivateKey($decryptedKey); $return = true; } From ef97481a0d7dcedba830bc423d623111f6c2e774 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 3 Jun 2013 23:41:57 +0200 Subject: [PATCH 13/24] changed redirect handling --- apps/files_encryption/files/error.php | 18 +++++++++++++ apps/files_encryption/lib/helper.php | 9 +++++++ apps/files_encryption/lib/stream.php | 25 +++++++------------ .../templates/invalid_private_key.php | 10 ++++++++ 4 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 apps/files_encryption/files/error.php create mode 100644 apps/files_encryption/templates/invalid_private_key.php diff --git a/apps/files_encryption/files/error.php b/apps/files_encryption/files/error.php new file mode 100644 index 0000000000..3118299b51 --- /dev/null +++ b/apps/files_encryption/files/error.php @@ -0,0 +1,18 @@ + array('message' => $l->t('Your private key is not valid! Maybe the your password was changed from outside.')))); + } else { + header('HTTP/1.0 404 ' . $l->t('Your private key is not valid! Maybe the your password was changed from outside.')); + $tmpl = new OC_Template('files_encryption', 'invalid_private_key', 'guest'); + $tmpl->printPage(); + } + + exit; +} +?> diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 3e581a6ee3..daa95f3f89 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -194,4 +194,13 @@ class Helper { return $relPath; } + + /** + * @brief redirect to a error page + */ + public static function redirectToErrorPage() { + $location = \OC_Helper::linkToAbsolute('apps/files_encryption/files', 'error.php'); + header('Location: ' . $location); + exit(); + } } \ No newline at end of file diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index dee5a7cccc..3c1eb2c5f5 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -116,6 +116,11 @@ class Stream { } else { + if($this->privateKey === false) { + // if private key is not valid redirect user to a error page + \OCA\Encryption\Helper::redirectToErrorPage(); + } + $this->size = $this->rootView->filesize($this->rawPath, $mode); } @@ -239,12 +244,8 @@ class Stream { // if there is no valid private key return false if ($this->privateKey === false) { - if (\OC_Util::isCallRegistered()) { - $l = \OC_L10N::get('core'); - \OCP\JSON::error(array('data' => array('message' => $l->t('Private key is not valid! Maybe the user password was changed from outside if so please change it back to gain access')))); - throw new \Exception('Private key for user "' . $this->userId - . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); - } + // if private key is not valid redirect user to a error page + \OCA\Encryption\Helper::redirectToErrorPage(); return false; } @@ -450,10 +451,6 @@ class Stream { // if there is no valid private key return false if ($this->privateKey === false) { - if (\OC_Util::isCallRegistered()) { - $l = \OC_L10N::get('core'); - \OCP\JSON::error(array('data' => array('message' => $l->t('Private key is not valid! Maybe the user password was changed from outside if so please change it back to gain access')))); - // cleanup if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb') { @@ -469,12 +466,8 @@ class Stream { \OC_FileProxy::$enabled = $proxyStatus; } - throw new \Exception('Private key for user "' . $this->userId - . '" is not valid! Maybe the user password was changed from outside if so please change it back to gain access'); - } - - - return false; + // if private key is not valid redirect user to a error page + \OCA\Encryption\Helper::redirectToErrorPage(); } if ( diff --git a/apps/files_encryption/templates/invalid_private_key.php b/apps/files_encryption/templates/invalid_private_key.php new file mode 100644 index 0000000000..b0ff1db599 --- /dev/null +++ b/apps/files_encryption/templates/invalid_private_key.php @@ -0,0 +1,10 @@ +
    +
  • + + + t('Your private key is not valid! Maybe the your password was changed from outside.')); ?> +
    + t('You can unlock your private key in your ')); ?> t('personal settings')); ?>. +
    +
  • +
From 14ac4fab054c332fe3a0e110bec6cb118bf83186 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 4 Jun 2013 00:41:47 +0200 Subject: [PATCH 14/24] better handling for http post --- apps/files_encryption/files/error.php | 4 ++++ apps/files_encryption/lib/helper.php | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/files/error.php b/apps/files_encryption/files/error.php index 3118299b51..37e94e5658 100644 --- a/apps/files_encryption/files/error.php +++ b/apps/files_encryption/files/error.php @@ -4,6 +4,10 @@ if (!isset($_)) { //also provide standalone error page $l = OC_L10N::get('files_encryption'); + if(isset($_GET['p']) && $_GET['p'] === '1') { + header('HTTP/1.0 404 ' . $l->t('Your private key is not valid! Maybe the your password was changed from outside.')); + } + // check if ajax request if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { \OCP\JSON::error(array('data' => array('message' => $l->t('Your private key is not valid! Maybe the your password was changed from outside.')))); diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index daa95f3f89..923cc2ce9d 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -200,7 +200,11 @@ class Helper { */ public static function redirectToErrorPage() { $location = \OC_Helper::linkToAbsolute('apps/files_encryption/files', 'error.php'); - header('Location: ' . $location); + $post = 0; + if(count($_POST) > 0) { + $post = 1; + } + header('Location: ' . $location . '?p=' . $post); exit(); } } \ No newline at end of file From 4ee7a428ae691352138550f9bbd003cbe4dbe35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 4 Jun 2013 10:49:58 +0200 Subject: [PATCH 15/24] link directly to the encryption settings --- apps/files_encryption/templates/invalid_private_key.php | 2 +- apps/files_encryption/templates/settings-personal.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/templates/invalid_private_key.php b/apps/files_encryption/templates/invalid_private_key.php index b0ff1db599..5c086d6514 100644 --- a/apps/files_encryption/templates/invalid_private_key.php +++ b/apps/files_encryption/templates/invalid_private_key.php @@ -1,6 +1,6 @@
From 7fc5151d95d7b4c6f27fd1d6207c93015da8315a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 5 Jun 2013 18:53:02 +0200 Subject: [PATCH 22/24] add a hint that the admin can recover your files; Don't let the user change the recovery settings if no private key is set --- .../files_encryption/templates/settings-personal.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/templates/settings-personal.php b/apps/files_encryption/templates/settings-personal.php index 8dab48828a..3851245320 100644 --- a/apps/files_encryption/templates/settings-personal.php +++ b/apps/files_encryption/templates/settings-personal.php @@ -7,9 +7,15 @@

- +
- t( "Set your old private key password to your current log-in password." ) ); ?> + t( "Set your old private key password to your current log-in password." ) ); ?> + t( " If you don't remember your old password you can ask your administrator to recover your files." ) ); + endif; ?> +
- +


From b25ab94a08ab9ba5e322043ac470d5352d456c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 7 Jun 2013 20:17:48 +0200 Subject: [PATCH 23/24] only check for recovery key if someone else than the user wants to change the password --- settings/ajax/changepassword.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/ajax/changepassword.php b/settings/ajax/changepassword.php index 90d213f179..e8adb8c959 100644 --- a/settings/ajax/changepassword.php +++ b/settings/ajax/changepassword.php @@ -27,7 +27,7 @@ if (is_null($userstatus)) { OC_JSON::error(array('data' => array('message' => 'Authentication error'))); exit(); } -if (\OCP\App::isEnabled('files_encryption')) { +if (\OCP\App::isEnabled('files_encryption') && $userstatus !== 'user') { $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), $username); $recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'); $recoveryEnabledForUser = $util->recoveryEnabledForUser(); From 64593e4b84fdd6881a43530461c50464303cc42e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 11 Jun 2013 10:02:55 +0200 Subject: [PATCH 24/24] update submodule --- 3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index a13af72fbe..d59b017922 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit a13af72fbe8983686fc47489a750e60319f68ac2 +Subproject commit d59b017922d9ac3bf985dee0eb721ec1a901ac72