From d7dca966a2a926be8b45ab337488143eac3ce9ba Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 30 Aug 2013 10:17:50 +0200 Subject: [PATCH 01/43] improved error messaging, initial commit --- apps/files_encryption/appinfo/database.xml | 7 +++ apps/files_encryption/appinfo/version | 2 +- apps/files_encryption/files/error.php | 2 +- apps/files_encryption/hooks/hooks.php | 29 +++++++----- apps/files_encryption/lib/helper.php | 44 ++++++++++++------ apps/files_encryption/lib/stream.php | 34 +++++++------- apps/files_encryption/lib/util.php | 52 ++++++++++++++++++++++ 7 files changed, 126 insertions(+), 44 deletions(-) diff --git a/apps/files_encryption/appinfo/database.xml b/apps/files_encryption/appinfo/database.xml index 4587930da0..cd5434b8c2 100644 --- a/apps/files_encryption/appinfo/database.xml +++ b/apps/files_encryption/appinfo/database.xml @@ -34,6 +34,13 @@ 0 Whether encryption migration has been performed + + initialized + integer + true + 0 + Did the user initialized the encryption app at least once + \ No newline at end of file diff --git a/apps/files_encryption/appinfo/version b/apps/files_encryption/appinfo/version index bd73f47072..2eb3c4fe4e 100644 --- a/apps/files_encryption/appinfo/version +++ b/apps/files_encryption/appinfo/version @@ -1 +1 @@ -0.4 +0.5 diff --git a/apps/files_encryption/files/error.php b/apps/files_encryption/files/error.php index 2dd27257ab..7a2bb1a281 100644 --- a/apps/files_encryption/files/error.php +++ b/apps/files_encryption/files/error.php @@ -4,7 +4,7 @@ if (!isset($_)) { //also provide standalone error page $l = OC_L10N::get('files_encryption'); - $errorMsg = $l->t('Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.'); + $errorMsg = $l->t('Your private key is not valid! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app. If this doesn\'t help maybe your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.'); if(isset($_GET['p']) && $_GET['p'] === '1') { header('HTTP/1.0 404 ' . $errorMsg); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index de306462d7..aefb274e1c 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -70,9 +70,11 @@ class Hooks { // If migration not yet done if ($ready) { + $util->setInitialized(Util::ENCRYPTION_INITIALIZED); + $userView = new \OC_FilesystemView('/' . $params['uid']); - // Set legacy encryption key if it exists, to support + // Set legacy encryption key if it exists, to support // depreciated encryption system if ( $userView->file_exists('encryption.key') @@ -143,6 +145,7 @@ class Hooks { * @brief If the password can't be changed within ownCloud, than update the key password in advance. */ public static function preSetPassphrase($params) { + return true; if ( ! \OC_User::canUserChangePassword($params['uid']) ) { self::setPassphrase($params); } @@ -153,7 +156,7 @@ class Hooks { * @param array $params keys: uid, password */ public static function setPassphrase($params) { - + return true; // Only attempt to change passphrase if server-side encryption // is in use (client-side encryption does not have access to // the necessary keys) @@ -248,7 +251,7 @@ class Hooks { $params['run'] = false; $params['error'] = $l->t('Following users are not set up for encryption:') . ' ' . join(', ' , $notConfigured); } - + } /** @@ -259,7 +262,7 @@ class Hooks { // NOTE: $params has keys: // [itemType] => file // itemSource -> int, filecache file ID - // [parent] => + // [parent] => // [itemTarget] => /13 // shareWith -> string, uid of user being shared to // fileTarget -> path of file being shared @@ -300,13 +303,13 @@ class Hooks { // NOTE: parent is folder but shared was a file! // we try to rebuild the missing path // some examples we face here - // user1 share folder1 with user2 folder1 has - // the following structure + // user1 share folder1 with user2 folder1 has + // the following structure // /folder1/subfolder1/subsubfolder1/somefile.txt // user2 re-share subfolder2 with user3 // user3 re-share somefile.txt user4 - // so our path should be - // /Shared/subfolder1/subsubfolder1/somefile.txt + // so our path should be + // /Shared/subfolder1/subsubfolder1/somefile.txt // while user3 is sharing if ($params['itemType'] === 'file') { @@ -537,14 +540,18 @@ class Hooks { } /** - * set migration status back to '0' so that all new files get encrypted + * set migration status and the init status back to '0' so that all new files get encrypted * if the app gets enabled again * @param array $params contains the app ID */ public static function preDisable($params) { if ($params['app'] === 'files_encryption') { - $query = \OC_DB::prepare('UPDATE `*PREFIX*encryption` SET `migration_status`=0'); - $query->execute(); + + $setMigrationStatus = \OC_DB::prepare('UPDATE `*PREFIX*encryption` SET `migration_status`=0'); + $setMigrationStatus->execute(); + + $setInitStatus = \OC_DB::prepare('UPDATE `*PREFIX*encryption` SET `initialized`=0'); + $setInitStatus->execute(); } } diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 0209a5d18b..105c5357e9 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -199,12 +199,12 @@ class Helper { public static function stripUserFilesPath($path) { $trimmed = ltrim($path, '/'); $split = explode('/', $trimmed); - + // it is not a file relative to data/user/files if (count($split) < 3 || $split[1] !== 'files') { return false; } - + $sliced = array_slice($split, 2); $relPath = implode('/', $sliced); @@ -219,30 +219,46 @@ class Helper { public static function getPathToRealFile($path) { $trimmed = ltrim($path, '/'); $split = explode('/', $trimmed); - + if (count($split) < 3 || $split[1] !== "files_versions") { return false; } - + $sliced = array_slice($split, 2); $realPath = implode('/', $sliced); //remove the last .v $realPath = substr($realPath, 0, strrpos($realPath, '.v')); return $realPath; - } - + } + /** * @brief redirect to a error page */ - public static function redirectToErrorPage() { - $location = \OC_Helper::linkToAbsolute('apps/files_encryption/files', 'error.php'); - $post = 0; - if(count($_POST) > 0) { - $post = 1; + public static function redirectToErrorPage($util) { + + $l = \OC_L10N::get('files_encryption'); + + if ($util->getInitialized() === false) { + $errorMsg = $l->t('Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app.'); + } else { + $errorMsg = $l->t('Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.'); } - header('Location: ' . $location . '?p=' . $post); - exit(); + + if(count($_POST) > 0) { + header('HTTP/1.0 404 ' . $errorMsg); + } + + // 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' => $errorMsg))); + } else { + header('HTTP/1.0 404 ' . $errorMsg); + $tmpl = new OC_Template('files_encryption', 'invalid_private_key', 'guest'); + $tmpl->printPage(); + } + + exit; } /** @@ -259,7 +275,7 @@ class Helper { return (bool) $result; } - + /** * check some common errors if the server isn't configured properly for encryption * @return bool true if configuration seems to be OK diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 335ea3733e..87b8dc3ee2 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -81,7 +81,7 @@ class Stream { * @return bool */ public function stream_open($path, $mode, $options, &$opened_path) { - + // assume that the file already exist before we decide it finally in getKey() $this->newFile = false; @@ -106,12 +106,12 @@ class Stream { if ($this->relPath === false) { $this->relPath = Helper::getPathToRealFile($this->rawPath); } - + if($this->relPath === false) { \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '" expecting a path to user/files or to user/files_versions', \OCP\Util::ERROR); return false; } - + // Disable fileproxies so we can get the file size and open the source file without recursive encryption $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -131,7 +131,7 @@ class Stream { if($this->privateKey === false) { // if private key is not valid redirect user to a error page - \OCA\Encryption\Helper::redirectToErrorPage(); + \OCA\Encryption\Helper::redirectToErrorPage($util); } $this->size = $this->rootView->filesize($this->rawPath, $mode); @@ -272,7 +272,7 @@ class Stream { } else { $this->newFile = true; - + return false; } @@ -296,9 +296,9 @@ class Stream { 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 + // 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 // get into an infinite loop $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -311,7 +311,7 @@ class Stream { $pointer = ftell($this->handle); // Get / generate the keyfile for the file we're handling - // If we're writing a new file (not overwriting an existing + // If we're writing a new file (not overwriting an existing // one), save the newly generated keyfile if (!$this->getKey()) { @@ -319,7 +319,7 @@ class Stream { } - // If extra data is left over from the last round, make sure it + // If extra data is left over from the last round, make sure it // is integrated into the next 6126 / 8192 block if ($this->writeCache) { @@ -344,12 +344,12 @@ class Stream { if ($remainingLength < 6126) { // Set writeCache to contents of $data - // The writeCache will be carried over to the - // next write round, and added to the start of - // $data to ensure that written blocks are - // always the correct length. If there is still - // data in writeCache after the writing round - // has finished, then the data will be written + // The writeCache will be carried over to the + // next write round, and added to the start of + // $data to ensure that written blocks are + // always the correct length. If there is still + // data in writeCache after the writing round + // has finished, then the data will be written // to disk by $this->flush(). $this->writeCache = $data; @@ -363,7 +363,7 @@ class Stream { $encrypted = $this->preWriteEncrypt($chunk, $this->plainKey); - // Write the data chunk to disk. This will be + // Write the data chunk to disk. This will be // attended to the last data chunk if the file // being handled totals more than 6126 bytes fwrite($this->handle, $encrypted); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index b8d6862349..edb9564e73 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -37,6 +37,8 @@ class Util { const MIGRATION_IN_PROGRESS = -1; // migration is running const MIGRATION_OPEN = 0; // user still needs to be migrated + const ENCRYPTION_INITIALIZED = 1; + const ENCRYPTION_NOT_INITIALIZED = 0; private $view; // OC_FilesystemView object for filesystem operations private $userId; // ID of the currently logged-in user @@ -1216,6 +1218,56 @@ class Util { return $return; } + /** + * set remember if the encryption app was already initialized or not + * @param type $status + */ + public function setInitialized($status) { + $sql = 'UPDATE `*PREFIX*encryption` SET `initialized` = ? WHERE `uid` = ?'; + $args = array($status, $this->userId); + $query = \OCP\DB::prepare($sql); + $query->execute($args); + } + + /** + * set remember if the encryption app was already initialized or not + */ + public function getInitialized() { + $sql = 'SELECT `initialized` FROM `*PREFIX*encryption` WHERE `uid` = ?'; + $args = array($this->userId); + $query = \OCP\DB::prepare($sql); + + $result = $query->execute($args); + $initializedStatus = null; + + if (\OCP\DB::isError($result)) { + \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); + } else { + if ($result->numRows() > 0) { + $row = $result->fetchRow(); + if (isset($row['initialized'])) { + $initializedStatus = (int)$row['initialized']; + } + } + } + + // If no record is found + if (empty($initializedStatus)) { + \OCP\Util::writeLog('Encryption library', "Could not get initialized status for " . $this->userId . ", no record found", \OCP\Util::ERROR); + return false; + // If a record is found + } else { + return (bool)$initializedStatus; + } + + + + $sql = 'UPDATE `*PREFIX*encryption` SET `initialized` = ? WHERE `uid` = ?'; + $args = array($status, $this->userId); + $query = \OCP\DB::prepare($sql); + $query->execute($args); + } + /** * @brief close migration mode after users data has been encrypted successfully * @return boolean From bab63c22eea058ea619de5c021d16803ba48ab8d Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 2 Sep 2013 11:26:11 +0200 Subject: [PATCH 02/43] encryption error messages, distinguish between a re-enabled encryption app and a password change from outside --- apps/files_encryption/appinfo/database.xml | 7 --- apps/files_encryption/hooks/hooks.php | 8 +-- apps/files_encryption/lib/helper.php | 4 +- apps/files_encryption/lib/session.php | 27 +++++++++ apps/files_encryption/lib/stream.php | 2 +- apps/files_encryption/lib/util.php | 60 ++----------------- apps/files_encryption/settings-personal.php | 5 +- .../templates/settings-personal.php | 10 ++-- settings/ajax/changepassword.php | 2 +- settings/templates/personal.php | 2 +- 10 files changed, 48 insertions(+), 79 deletions(-) diff --git a/apps/files_encryption/appinfo/database.xml b/apps/files_encryption/appinfo/database.xml index cd5434b8c2..4587930da0 100644 --- a/apps/files_encryption/appinfo/database.xml +++ b/apps/files_encryption/appinfo/database.xml @@ -34,13 +34,6 @@ 0 Whether encryption migration has been performed - - initialized - integer - true - 0 - Did the user initialized the encryption app at least once - \ No newline at end of file diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index aefb274e1c..4c6122b7c2 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -70,8 +70,6 @@ class Hooks { // If migration not yet done if ($ready) { - $util->setInitialized(Util::ENCRYPTION_INITIALIZED); - $userView = new \OC_FilesystemView('/' . $params['uid']); // Set legacy encryption key if it exists, to support @@ -145,7 +143,6 @@ class Hooks { * @brief If the password can't be changed within ownCloud, than update the key password in advance. */ public static function preSetPassphrase($params) { - return true; if ( ! \OC_User::canUserChangePassword($params['uid']) ) { self::setPassphrase($params); } @@ -156,7 +153,6 @@ class Hooks { * @param array $params keys: uid, password */ public static function setPassphrase($params) { - return true; // Only attempt to change passphrase if server-side encryption // is in use (client-side encryption does not have access to // the necessary keys) @@ -550,8 +546,8 @@ class Hooks { $setMigrationStatus = \OC_DB::prepare('UPDATE `*PREFIX*encryption` SET `migration_status`=0'); $setMigrationStatus->execute(); - $setInitStatus = \OC_DB::prepare('UPDATE `*PREFIX*encryption` SET `initialized`=0'); - $setInitStatus->execute(); + $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); + $session->setInitialized(false); } } diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 105c5357e9..7d466b8852 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -235,11 +235,11 @@ class Helper { /** * @brief redirect to a error page */ - public static function redirectToErrorPage($util) { + public static function redirectToErrorPage($session) { $l = \OC_L10N::get('files_encryption'); - if ($util->getInitialized() === false) { + if ($session->getInitialized() === false) { $errorMsg = $l->t('Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app.'); } else { $errorMsg = $l->t('Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.'); diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 1911386cd1..f5ce7083af 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -112,6 +112,33 @@ class Session { } + /** + * @brief Sets status if we tried to initialize the encyption app + * @param bool $privateKey true=initialized false=not initialized + * @return bool + */ + public function setInitialized($init) { + + \OC::$session->set('encryptionInitialized', $init); + + return true; + + } + + + /** + * @brief Gets status if we already tried to initialize the encryption app + * @returns bool + * + */ + public function getInitialized() { + if (!is_null(\OC::$session->get('encryptionInitialized'))) { + return \OC::$session->get('encryptionInitialized'); + } else { + return false; + } + } + /** * @brief Gets user or public share private key from session * @returns string $privateKey The user's plaintext private key diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 87b8dc3ee2..9215352aa7 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -131,7 +131,7 @@ class Stream { if($this->privateKey === false) { // if private key is not valid redirect user to a error page - \OCA\Encryption\Helper::redirectToErrorPage($util); + \OCA\Encryption\Helper::redirectToErrorPage($this->session); } $this->size = $this->rootView->filesize($this->rawPath, $mode); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index edb9564e73..17096a787f 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -37,9 +37,6 @@ class Util { const MIGRATION_IN_PROGRESS = -1; // migration is running const MIGRATION_OPEN = 0; // user still needs to be migrated - const ENCRYPTION_INITIALIZED = 1; - const ENCRYPTION_NOT_INITIALIZED = 0; - private $view; // OC_FilesystemView object for filesystem operations private $userId; // ID of the currently logged-in user private $client; // Client side encryption mode flag @@ -1218,56 +1215,6 @@ class Util { return $return; } - /** - * set remember if the encryption app was already initialized or not - * @param type $status - */ - public function setInitialized($status) { - $sql = 'UPDATE `*PREFIX*encryption` SET `initialized` = ? WHERE `uid` = ?'; - $args = array($status, $this->userId); - $query = \OCP\DB::prepare($sql); - $query->execute($args); - } - - /** - * set remember if the encryption app was already initialized or not - */ - public function getInitialized() { - $sql = 'SELECT `initialized` FROM `*PREFIX*encryption` WHERE `uid` = ?'; - $args = array($this->userId); - $query = \OCP\DB::prepare($sql); - - $result = $query->execute($args); - $initializedStatus = null; - - if (\OCP\DB::isError($result)) { - \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); - } else { - if ($result->numRows() > 0) { - $row = $result->fetchRow(); - if (isset($row['initialized'])) { - $initializedStatus = (int)$row['initialized']; - } - } - } - - // If no record is found - if (empty($initializedStatus)) { - \OCP\Util::writeLog('Encryption library', "Could not get initialized status for " . $this->userId . ", no record found", \OCP\Util::ERROR); - return false; - // If a record is found - } else { - return (bool)$initializedStatus; - } - - - - $sql = 'UPDATE `*PREFIX*encryption` SET `initialized` = ? WHERE `uid` = ?'; - $args = array($status, $this->userId); - $query = \OCP\DB::prepare($sql); - $query->execute($args); - } - /** * @brief close migration mode after users data has been encrypted successfully * @return boolean @@ -1774,6 +1721,11 @@ class Util { */ public function initEncryption($params) { + $session = new \OCA\Encryption\Session($this->view); + + // we tried to initialize the encryption app for this session + $session->setInitialized(true); + $encryptedKey = Keymanager::getPrivateKey($this->view, $params['uid']); $privateKey = Crypt::decryptPrivateKey($encryptedKey, $params['password']); @@ -1784,8 +1736,6 @@ class Util { return false; } - $session = new \OCA\Encryption\Session($this->view); - $session->setPrivateKey($privateKey); return $session; diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php index 589219f32a..c0c91bdf65 100644 --- a/apps/files_encryption/settings-personal.php +++ b/apps/files_encryption/settings-personal.php @@ -16,7 +16,9 @@ $view = new \OC_FilesystemView('/'); $util = new \OCA\Encryption\Util($view, $user); $session = new \OCA\Encryption\Session($view); -$privateKeySet = $session->getPrivateKey() !== false; +$privateKeySet = $session->getPrivateKey() !== false; +// was the key successfully initialized during log-in +$initialized = $session->getInitialized(); $recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'); $recoveryEnabledForUser = $util->recoveryEnabledForUser(); @@ -31,6 +33,7 @@ if ($recoveryAdminEnabled || !$privateKeySet) { $tmpl->assign('recoveryEnabled', $recoveryAdminEnabled); $tmpl->assign('recoveryEnabledForUser', $recoveryEnabledForUser); $tmpl->assign('privateKeySet', $privateKeySet); + $tmpl->assign('initialized', $initialized); $result = $tmpl->fetchPage(); } diff --git a/apps/files_encryption/templates/settings-personal.php b/apps/files_encryption/templates/settings-personal.php index 3851245320..ff04556dd5 100644 --- a/apps/files_encryption/templates/settings-personal.php +++ b/apps/files_encryption/templates/settings-personal.php @@ -4,7 +4,7 @@ t( 'Encryption' ) ); ?> - +


t( "Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" ) ); ?>
- /> t( "Enabled" ) ); ?>
- - t('Your password was changed');?>

- From 5e508f1ccbd3b83ed11f7eab35fea43e1583caf3 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 2 Sep 2013 11:34:28 +0200 Subject: [PATCH 03/43] improved documentation of the methods --- apps/files_encryption/lib/session.php | 3 +++ apps/files_encryption/settings-personal.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index f5ce7083af..648e6e9ab0 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -116,6 +116,8 @@ class Session { * @brief Sets status if we tried to initialize the encyption app * @param bool $privateKey true=initialized false=not initialized * @return bool + * + * @note this doesn not indicate of the init was successful, we just remeber the try! */ public function setInitialized($init) { @@ -130,6 +132,7 @@ class Session { * @brief Gets status if we already tried to initialize the encryption app * @returns bool * + * @note this doesn not indicate of the init was successful, we just remeber the try! */ public function getInitialized() { if (!is_null(\OC::$session->get('encryptionInitialized'))) { diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php index c0c91bdf65..ffcb99602e 100644 --- a/apps/files_encryption/settings-personal.php +++ b/apps/files_encryption/settings-personal.php @@ -17,7 +17,7 @@ $util = new \OCA\Encryption\Util($view, $user); $session = new \OCA\Encryption\Session($view); $privateKeySet = $session->getPrivateKey() !== false; -// was the key successfully initialized during log-in +// did we tried to initialize the keys for this session? $initialized = $session->getInitialized(); $recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'); From 6572ca811fc56c71b4efc970668741630acbd63c Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 2 Sep 2013 11:36:20 +0200 Subject: [PATCH 04/43] error.php no longer needed --- apps/files_encryption/files/error.php | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 apps/files_encryption/files/error.php diff --git a/apps/files_encryption/files/error.php b/apps/files_encryption/files/error.php deleted file mode 100644 index 7a2bb1a281..0000000000 --- a/apps/files_encryption/files/error.php +++ /dev/null @@ -1,23 +0,0 @@ -t('Your private key is not valid! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app. If this doesn\'t help maybe your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.'); - - if(isset($_GET['p']) && $_GET['p'] === '1') { - header('HTTP/1.0 404 ' . $errorMsg); - } - - // 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' => $errorMsg))); - } else { - header('HTTP/1.0 404 ' . $errorMsg); - $tmpl = new OC_Template('files_encryption', 'invalid_private_key', 'guest'); - $tmpl->printPage(); - } - - exit; -} From 69b1625f0e368e65771fef473f4b4d4a13456354 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 6 Sep 2013 12:27:25 +0200 Subject: [PATCH 05/43] re-added error.php --- apps/files_encryption/files/error.php | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 apps/files_encryption/files/error.php diff --git a/apps/files_encryption/files/error.php b/apps/files_encryption/files/error.php new file mode 100644 index 0000000000..ac0c026916 --- /dev/null +++ b/apps/files_encryption/files/error.php @@ -0,0 +1,33 @@ +t('Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app.'); + $init = '0'; + } else { + $errorMsg = $l->t('Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.'); + $init = '1'; + } + + if (isset($_GET['p']) && $_GET['p'] === '1') { + header('HTTP/1.0 404 ' . $errorMsg); + } + +// 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' => $errorMsg))); + } else { + header('HTTP/1.0 404 ' . $errorMsg); + $tmpl = new OC_Template('files_encryption', 'invalid_private_key', 'guest'); + $tmpl->assign('message', $errorMsg); + $tmpl->assign('init', $init); + $tmpl->printPage(); + } + + exit; +} + From fb462e83ccde5c46565c23545c5eb894acbd6fd3 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 6 Sep 2013 12:27:40 +0200 Subject: [PATCH 06/43] no longer enforce log out, but provide useful errors/warnings instead --- apps/files/index.php | 7 ++++- apps/files/js/files.js | 9 +++++++ apps/files/templates/index.php | 1 + .../ajax/updatePrivateKeyPassword.php | 1 + apps/files_encryption/appinfo/app.php | 17 ------------ apps/files_encryption/hooks/hooks.php | 2 +- apps/files_encryption/lib/helper.php | 27 +++++-------------- apps/files_encryption/lib/session.php | 15 +++++++---- apps/files_encryption/lib/stream.php | 2 +- apps/files_encryption/lib/util.php | 3 ++- .../templates/invalid_private_key.php | 6 +++-- 11 files changed, 42 insertions(+), 48 deletions(-) diff --git a/apps/files/index.php b/apps/files/index.php index f1e120c872..b81ba2bdde 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -124,8 +124,12 @@ if ($needUpgrade) { $storageInfo=OC_Helper::getStorageInfo($dir); $maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); $publicUploadEnabled = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes'); + // if the encryption app is disabled, than everything is fine + $encryptionInitStatus = \OCA\Encryption\Session::INIT_SUCCESSFUL; if (OC_App::isEnabled('files_encryption')) { $publicUploadEnabled = 'no'; + $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); + $encryptionInitStatus = $session->getInitialized(); } $trashEnabled = \OCP\App::isEnabled('files_trashbin'); @@ -133,7 +137,7 @@ if ($needUpgrade) { if ($trashEnabled) { $trashEmpty = \OCA\Files_Trashbin\Trashbin::isEmpty($user); } - + OCP\Util::addscript('files', 'fileactions'); OCP\Util::addscript('files', 'files'); OCP\Util::addscript('files', 'keyboardshortcuts'); @@ -153,5 +157,6 @@ if ($needUpgrade) { $tmpl->assign('isPublic', false); $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); $tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); + $tmpl->assign("encryptionInitStatus", $encryptionInitStatus); $tmpl->printPage(); } diff --git a/apps/files/js/files.js b/apps/files/js/files.js index d729077ea7..63c3544b53 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -90,6 +90,15 @@ Files={ } var encryptedFiles = $('#encryptedFiles').val(); + var initStatus = $('#encryptionInitStatus').val(); + if (initStatus === '0') { // enc not initialized, but should be + OC.Notification.show(t('files_encryption', 'Encryption App is enabled but your keys are not initialized, please log-out and log-in again')); + return; + } + if (initStatus === '1') { // encryption tried to init but failed + OC.Notification.show(t('files_encryption', 'Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.')); + return; + } if (encryptedFiles === '1') { OC.Notification.show(t('files_encryption', 'Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.')); return; diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 24cb8c2fe5..e17273e47b 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -123,3 +123,4 @@ + \ No newline at end of file diff --git a/apps/files_encryption/ajax/updatePrivateKeyPassword.php b/apps/files_encryption/ajax/updatePrivateKeyPassword.php index 1e6644da57..29c72952ae 100644 --- a/apps/files_encryption/ajax/updatePrivateKeyPassword.php +++ b/apps/files_encryption/ajax/updatePrivateKeyPassword.php @@ -48,6 +48,7 @@ if ($decryptedKey) { // success or failure if ($return) { + $session->setInitialized(\OCA\Encryption\Session::INIT_SUCCESSFUL); \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.')))); diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 90a9984e27..cd26cd10cd 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -41,23 +41,6 @@ if (!OC_Config::getValue('maintenance', false)) { if($sessionReady) { $session = new \OCA\Encryption\Session($view); } - - $user = \OCP\USER::getUser(); - // check if user has a private key - if ($sessionReady === false - || (!$view->file_exists('/' . $user . '/files_encryption/' . $user . '.private.key') - && OCA\Encryption\Crypt::mode() === 'server') - ) { - - // Force the user to log-in again if the encryption key isn't unlocked - // (happens when a user is logged in before the encryption app is - // enabled) - OCP\User::logout(); - - header("Location: " . OC::$WEBROOT . '/'); - - exit(); - } } } else { // logout user if we are in maintenance to force re-login diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 4c6122b7c2..c945deeea0 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -547,7 +547,7 @@ class Hooks { $setMigrationStatus->execute(); $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); - $session->setInitialized(false); + $session->setInitialized(\OCA\Encryption\Session::NOT_INITIALIZED); } } diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 7d466b8852..048473ce84 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -237,28 +237,15 @@ class Helper { */ public static function redirectToErrorPage($session) { - $l = \OC_L10N::get('files_encryption'); - - if ($session->getInitialized() === false) { - $errorMsg = $l->t('Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app.'); - } else { - $errorMsg = $l->t('Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files.'); - } + $init = $session->getInitialized(); + $location = \OC_Helper::linkToAbsolute('apps/files_encryption/files', 'error.php'); + $post = 0; if(count($_POST) > 0) { - header('HTTP/1.0 404 ' . $errorMsg); - } - - // 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' => $errorMsg))); - } else { - header('HTTP/1.0 404 ' . $errorMsg); - $tmpl = new OC_Template('files_encryption', 'invalid_private_key', 'guest'); - $tmpl->printPage(); - } - - exit; + $post = 1; + } + header('Location: ' . $location . '?p=' . $post . '&i=' . $init); + exit(); } /** diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 648e6e9ab0..25f2198181 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -30,6 +30,11 @@ class Session { private $view; + const NOT_INITIALIZED = '0'; + const INIT_EXECUTED = '1'; + const INIT_SUCCESSFUL = '2'; + + /** * @brief if session is started, check if ownCloud key pair is set up, if not create it * @param \OC_FilesystemView $view @@ -113,10 +118,10 @@ class Session { } /** - * @brief Sets status if we tried to initialize the encyption app - * @param bool $privateKey true=initialized false=not initialized + * @brief Sets status of encryption app + * @param string $init INIT_SUCCESSFUL, INIT_EXECUTED, NOT_INOITIALIZED * @return bool - * + * * @note this doesn not indicate of the init was successful, we just remeber the try! */ public function setInitialized($init) { @@ -130,7 +135,7 @@ class Session { /** * @brief Gets status if we already tried to initialize the encryption app - * @returns bool + * @returns init status INIT_SUCCESSFUL, INIT_EXECUTED, NOT_INOITIALIZED * * @note this doesn not indicate of the init was successful, we just remeber the try! */ @@ -138,7 +143,7 @@ class Session { if (!is_null(\OC::$session->get('encryptionInitialized'))) { return \OC::$session->get('encryptionInitialized'); } else { - return false; + return self::NOT_INITIALIZED; } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 9215352aa7..c6db10ce40 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -128,7 +128,7 @@ class Stream { $this->unencryptedSize = 0; } else { - +\OCA\Encryption\Helper::redirectToErrorPage($this->session); if($this->privateKey === false) { // if private key is not valid redirect user to a error page \OCA\Encryption\Helper::redirectToErrorPage($this->session); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 17096a787f..7a19f95464 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -1724,7 +1724,7 @@ class Util { $session = new \OCA\Encryption\Session($this->view); // we tried to initialize the encryption app for this session - $session->setInitialized(true); + $session->setInitialized(\OCA\Encryption\Session::INIT_EXECUTED); $encryptedKey = Keymanager::getPrivateKey($this->view, $params['uid']); @@ -1737,6 +1737,7 @@ class Util { } $session->setPrivateKey($privateKey); + $session->setInitialized(\OCA\Encryption\Session::INIT_SUCCESSFUL); return $session; } diff --git a/apps/files_encryption/templates/invalid_private_key.php b/apps/files_encryption/templates/invalid_private_key.php index 5c086d6514..9af65f831b 100644 --- a/apps/files_encryption/templates/invalid_private_key.php +++ b/apps/files_encryption/templates/invalid_private_key.php @@ -2,9 +2,11 @@
  • - 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')); ?>. + + p($l->t('Go directly to your ')); ?> t('personal settings')); ?>. +
  • From 1558cb860c2fb26fdde14fce2a16acbb29d12b3e Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 6 Sep 2013 13:16:48 +0200 Subject: [PATCH 07/43] remove test code --- apps/files_encryption/lib/stream.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index c6db10ce40..9215352aa7 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -128,7 +128,7 @@ class Stream { $this->unencryptedSize = 0; } else { -\OCA\Encryption\Helper::redirectToErrorPage($this->session); + if($this->privateKey === false) { // if private key is not valid redirect user to a error page \OCA\Encryption\Helper::redirectToErrorPage($this->session); From 5fb0e257a4e7b16024389261cfe924f53deb69ae Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 18 Sep 2013 16:03:53 +0200 Subject: [PATCH 08/43] let user repeat the recovery key password to prevent typos --- apps/files_encryption/js/settings-admin.js | 36 ++++++++++--------- .../templates/settings-admin.php | 28 +++++++++------ 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/apps/files_encryption/js/settings-admin.js b/apps/files_encryption/js/settings-admin.js index 6647c621e7..82fdb51708 100644 --- a/apps/files_encryption/js/settings-admin.js +++ b/apps/files_encryption/js/settings-admin.js @@ -1,6 +1,6 @@ /** - * Copyright (c) 2013, Sam Tuke , Robin Appelman - * + * Copyright (c) 2013, Sam Tuke , Robin Appelman + * , Bjoern Schiessle * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. */ @@ -31,22 +31,23 @@ $(document).ready(function(){ // Trigger ajax on recoveryAdmin status change var enabledStatus = $('#adminEnableRecovery').val(); - $('input:password[name="recoveryPassword"]').keyup(function(event) { - var recoveryPassword = $( '#recoveryPassword' ).val(); + $('input:password[name="encryptionRecoveryPassword"]').keyup(function(event) { + var recoveryPassword = $( '#encryptionRecoveryPassword' ).val(); + var recoveryPasswordRepeated = $( '#repeatEncryptionRecoveryPassword' ).val(); var checkedButton = $('input:radio[name="adminEnableRecovery"]:checked').val(); var uncheckedValue = (1+parseInt(checkedButton)) % 2; - if (recoveryPassword != '' ) { + if (recoveryPassword !== '' && recoveryPassword === recoveryPasswordRepeated) { $('input:radio[name="adminEnableRecovery"][value="'+uncheckedValue.toString()+'"]').removeAttr("disabled"); } else { $('input:radio[name="adminEnableRecovery"][value="'+uncheckedValue.toString()+'"]').attr("disabled", "true"); } }); - $( 'input:radio[name="adminEnableRecovery"]' ).change( + $( 'input:radio[name="adminEnableRecovery"]' ).change( function() { var recoveryStatus = $( this ).val(); var oldStatus = (1+parseInt(recoveryStatus)) % 2; - var recoveryPassword = $( '#recoveryPassword' ).val(); + var recoveryPassword = $( '#encryptionRecoveryPassword' ).val(); $.post( OC.filePath( 'files_encryption', 'ajax', 'adminrecovery.php' ) , { adminEnableRecovery: recoveryStatus, recoveryPassword: recoveryPassword } @@ -57,11 +58,10 @@ $(document).ready(function(){ } else { OC.Notification.hide(); if (recoveryStatus === "0") { - $('button:button[name="submitChangeRecoveryKey"]').attr("disabled", "true"); - $('input:password[name="changeRecoveryPassword"]').attr("disabled", "true"); - $('input:password[name="changeRecoveryPassword"]').val(""); + $('p[name="changeRecoveryPasswordBlock"]').attr("class", "hidden"); } else { - $('input:password[name="changeRecoveryPassword"]').removeAttr("disabled"); + $('input:password[name="changeRecoveryPassword"]').val(""); + $('p[name="changeRecoveryPasswordBlock"]').removeAttr("class"); } } } @@ -72,9 +72,11 @@ $(document).ready(function(){ // change recovery password $('input:password[name="changeRecoveryPassword"]').keyup(function(event) { - var oldRecoveryPassword = $('input:password[id="oldRecoveryPassword"]').val(); - var newRecoveryPassword = $('input:password[id="newRecoveryPassword"]').val(); - if (newRecoveryPassword != '' && oldRecoveryPassword != '' ) { + var oldRecoveryPassword = $('#oldEncryptionRecoveryPassword').val(); + var newRecoveryPassword = $('#newEncryptionRecoveryPassword').val(); + var newRecoveryPasswordRepeated = $('#repeatedNewEncryptionRecoveryPassword').val(); + console.log("new: " + newRecoveryPassword + " - repeated: " + newRecoveryPasswordRepeated); + if (newRecoveryPassword !== '' && oldRecoveryPassword !== '' && newRecoveryPassword === newRecoveryPasswordRepeated) { $('button:button[name="submitChangeRecoveryKey"]').removeAttr("disabled"); } else { $('button:button[name="submitChangeRecoveryKey"]').attr("disabled", "true"); @@ -83,8 +85,8 @@ $(document).ready(function(){ $('button:button[name="submitChangeRecoveryKey"]').click(function() { - var oldRecoveryPassword = $('input:password[id="oldRecoveryPassword"]').val(); - var newRecoveryPassword = $('input:password[id="newRecoveryPassword"]').val(); + var oldRecoveryPassword = $('#oldEncryptionRecoveryPassword').val(); + var newRecoveryPassword = $('#newEncryptionRecoveryPassword').val(); OC.msg.startSaving('#encryption .msg'); $.post( OC.filePath( 'files_encryption', 'ajax', 'changeRecoveryPassword.php' ) @@ -98,5 +100,5 @@ $(document).ready(function(){ } ); }); - + }); diff --git a/apps/files_encryption/templates/settings-admin.php b/apps/files_encryption/templates/settings-admin.php index f5f7582c2a..3a6adc09f4 100644 --- a/apps/files_encryption/templates/settings-admin.php +++ b/apps/files_encryption/templates/settings-admin.php @@ -10,14 +10,17 @@ t("Enable recovery key (allow to recover users files in case of password loss):")); ?>

    - +
    + + +
    /> + /> t("Enabled")); ?>
    @@ -25,27 +28,32 @@ type='radio' name='adminEnableRecovery' value='0' - /> + /> t("Disabled")); ?>



    -

    +

    > t("Change recovery key password:")); ?>

    /> - + id="oldEncryptionRecoveryPassword" + +

    /> - + id="newEncryptionRecoveryPassword" + +
    + t("Repeat New Recovery key password")); ?>