diff options
author | Björn Schießle <schiessle@owncloud.com> | 2014-05-13 09:25:16 -0400 |
---|---|---|
committer | Björn Schießle <schiessle@owncloud.com> | 2014-05-13 09:25:16 -0400 |
commit | b8de1e5d716c416beae328506e368cd0554509e1 (patch) | |
tree | 8b13942c27547f4c4266699efc445b0bfe96296d | |
parent | e934129bf6125c50ccede651b544d7ab07d5378a (diff) | |
parent | a9ac11718e62017c70682f99eb35b43b1ef9c498 (diff) | |
download | nextcloud-server-b8de1e5d716c416beae328506e368cd0554509e1.tar.gz nextcloud-server-b8de1e5d716c416beae328506e368cd0554509e1.zip |
Merge pull request #8398 from owncloud/enc_backup_keys
backup the encryption key after the encryption was disabled
-rw-r--r-- | apps/files_encryption/lib/util.php | 4 | ||||
-rwxr-xr-x | apps/files_encryption/tests/util.php | 11 | ||||
-rwxr-xr-x | lib/private/util.php | 36 | ||||
-rw-r--r-- | settings/ajax/deletekeys.php | 17 | ||||
-rw-r--r-- | settings/ajax/restorekeys.php | 24 | ||||
-rw-r--r-- | settings/js/personal.js | 61 | ||||
-rw-r--r-- | settings/personal.php | 6 | ||||
-rw-r--r-- | settings/routes.php | 4 | ||||
-rw-r--r-- | settings/templates/personal.php | 35 |
9 files changed, 176 insertions, 22 deletions
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 37fdcaceaa5..b96e4590507 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -788,8 +788,8 @@ class Util { } if ($successful) { - $this->view->deleteAll($this->keyfilesPath); - $this->view->deleteAll($this->shareKeysPath); + $this->view->rename($this->keyfilesPath, $this->keyfilesPath . '.backup'); + $this->view->rename($this->shareKeysPath, $this->shareKeysPath . '.backup'); } \OC_FileProxy::$enabled = true; diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index de83f6bca2b..11961f27675 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -413,8 +413,16 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { // file should no longer be encrypted $this->assertEquals(0, $fileInfoUnencrypted['encrypted']); + // check if the keys where moved to the backup location + $this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/keyfiles.backup')); + $this->assertTrue($this->view->file_exists($this->userId . '/files_encryption/keyfiles.backup/' . $filename . '.key')); + $this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/share-keys.backup')); + $this->assertTrue($this->view->file_exists($this->userId . '/files_encryption/share-keys.backup/' . $filename . '.' . $user . '.shareKey')); + // cleanup $this->view->unlink($this->userId . '/files/' . $filename); + $this->view->deleteAll($this->userId . '/files_encryption/keyfiles.backup'); + $this->view->deleteAll($this->userId . '/files_encryption/share-keys.backup'); OC_App::enable('files_encryption'); } @@ -485,8 +493,11 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/keyfiles/')); $this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/share-keys/')); + //cleanup $this->view->unlink($this->userId . '/files/' . $file1); $this->view->unlink($this->userId . '/files/' . $file2); + $this->view->deleteAll($this->userId . '/files_encryption/keyfiles.backup'); + $this->view->deleteAll($this->userId . '/files_encryption/share-keys.backup'); } diff --git a/lib/private/util.php b/lib/private/util.php index e2005d31c38..96d80beb4d1 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -551,6 +551,27 @@ class OC_Util { } /** + * @brief check if a backup from the encryption keys exists + * @return boolean + */ + public static function backupKeysExists() { + //check if encryption was enabled in the past + $backupExists = false; + if (OC_App::isEnabled('files_encryption') === false) { + $view = new OC\Files\View('/' . OCP\User::getUser()); + $backupPath = '/files_encryption/keyfiles.backup'; + if ($view->is_dir($backupPath)) { + $dircontent = $view->getDirectoryContent($backupPath); + if (!empty($dircontent)) { + $backupExists = true; + } + } + } + + return $backupExists; + } + + /** * @brief Check for correct file permissions of data directory * @param string $dataDirectory * @return array arrays with error messages and hints @@ -837,7 +858,7 @@ class OC_Util { if (!\OC_Config::getValue("check_for_working_htaccess", true)) { return true; } - + // testdata $fileName = '/htaccesstest.txt'; $testContent = 'testcontent'; @@ -1082,7 +1103,7 @@ class OC_Util { curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($curl, CURLOPT_URL, $url); - + curl_setopt($curl, CURLOPT_USERAGENT, "ownCloud Server Crawler"); if(OC_Config::getValue('proxy', '') != '') { @@ -1091,17 +1112,16 @@ class OC_Util { if(OC_Config::getValue('proxyuserpwd', '') != '') { curl_setopt($curl, CURLOPT_PROXYUSERPWD, OC_Config::getValue('proxyuserpwd')); } - - if (ini_get('open_basedir') === '' && ini_get('safe_mode' === 'Off')) { + + if (ini_get('open_basedir') === '' && ini_get('safe_mode' === 'Off')) { curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_MAXREDIRS, $max_redirects); $data = curl_exec($curl); } else { curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); $mr = $max_redirects; - if ($mr > 0) { + if ($mr > 0) { $newURL = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); - $rcurl = curl_copy_handle($curl); curl_setopt($rcurl, CURLOPT_HEADER, true); curl_setopt($rcurl, CURLOPT_NOBODY, true); @@ -1125,9 +1145,9 @@ class OC_Util { curl_close($rcurl); if ($mr > 0) { curl_setopt($curl, CURLOPT_URL, $newURL); - } + } } - + if($mr == 0 && $max_redirects > 0) { $data = false; } else { diff --git a/settings/ajax/deletekeys.php b/settings/ajax/deletekeys.php new file mode 100644 index 00000000000..1f84452e117 --- /dev/null +++ b/settings/ajax/deletekeys.php @@ -0,0 +1,17 @@ +<?php + +OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); + +$l = \OC_L10N::get('settings'); +$user = \OC_User::getUser(); +$view = new \OC\Files\View('/' . $user . '/files_encryption'); + +$keyfilesDeleted = $view->deleteAll('keyfiles.backup'); +$sharekeysDeleted = $view->deleteAll('share-keys.backup'); + +if ($keyfilesDeleted && $sharekeysDeleted) { + \OCP\JSON::success(array('data' => array('message' => $l->t('Encryption keys deleted permanently')))); +} else { + \OCP\JSON::error(array('data' => array('message' => $l->t('Couldn\'t permanently delete your encryption keys, please check your owncloud.log or ask your administrator')))); +} diff --git a/settings/ajax/restorekeys.php b/settings/ajax/restorekeys.php new file mode 100644 index 00000000000..68e19c90457 --- /dev/null +++ b/settings/ajax/restorekeys.php @@ -0,0 +1,24 @@ +<?php + +OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); + +$l = \OC_L10N::get('settings'); +$user = \OC_User::getUser(); +$view = new \OC\Files\View('/' . $user . '/files_encryption'); + +$keyfilesRestored = $view->rename('keyfiles.backup', 'keyfiles'); +$sharekeysRestored = $view->rename('share-keys.backup' , 'share-keys'); + +if ($keyfilesRestored && $sharekeysRestored) { + \OCP\JSON::success(array('data' => array('message' => $l->t('Backups restored successfully')))); +} else { + // if one of the move operation was succesful we remove the files back to have a consistent state + if($keyfilesRestored) { + $view->rename('keyfiles', 'keyfiles.backup'); + } + if($sharekeysRestored) { + $view->rename('share-keys' , 'share-keys.backup'); + } + \OCP\JSON::error(array('data' => array('message' => $l->t('Couldn\'t restore your encryption keys, please check your owncloud.log or ask your administrator')))); +} diff --git a/settings/js/personal.js b/settings/js/personal.js index c1f1ef7466b..f297e3c1b1a 100644 --- a/settings/js/personal.js +++ b/settings/js/personal.js @@ -212,17 +212,30 @@ $(document).ready(function(){ OC.Encryption.decryptAll(privateKeyPassword); }); + + $('button:button[name="submitRestoreKeys"]').click(function() { + $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true); + $('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true); + OC.Encryption.restoreKeys(); + }); + + $('button:button[name="submitDeleteKeys"]').click(function() { + $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true); + $('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true); + OC.Encryption.deleteKeys(); + }); + $('#decryptAll input:password[name="privateKeyPassword"]').keyup(function(event) { var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val(); if (privateKeyPassword !== '' ) { - $('#decryptAll button:button[name="submitDecryptAll"]').removeAttr("disabled"); + $('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", false); if(event.which === 13) { $('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true); $('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true); OC.Encryption.decryptAll(privateKeyPassword); } } else { - $('#decryptAll button:button[name="submitDecryptAll"]').attr("disabled", "true"); + $('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true); } }); @@ -294,29 +307,59 @@ $(document).ready(function(){ OC.Encryption = { decryptAll: function(password) { - OC.Encryption.msg.startDecrypting('#decryptAll .msg'); + var message = t('settings', 'Decrypting files... Please wait, this can take some time.'); + OC.Encryption.msg.start('#decryptAll .msg', message); $.post('ajax/decryptall.php', {password:password}, function(data) { if (data.status === "error") { - OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data); - $('#decryptAll input:password[name="privateKeyPassword"]').removeAttr("disabled"); + OC.Encryption.msg.finished('#decryptAll .msg', data); + $('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", false); + } else { + OC.Encryption.msg.finished('#decryptAll .msg', data); + } + $('#restoreBackupKeys').removeClass('hidden'); + }); + }, + + deleteKeys: function() { + var message = t('settings', 'Delete encryptin keys permanently.'); + OC.Encryption.msg.start('#restoreBackupKeys .msg', message); + $.post('ajax/deletekeys.php', null, function(data) { + if (data.status === "error") { + OC.Encryption.msg.finished('#restoreBackupKeys .msg', data); + $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false); + $('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", false); + } else { + OC.Encryption.msg.finished('#restoreBackupKeys .msg', data); + } + }); + }, + + restoreKeys: function() { + var message = t('settings', 'Restore encryptin keys.'); + OC.Encryption.msg.start('#restoreBackupKeys .msg', message); + $.post('ajax/restorekeys.php', {}, function(data) { + if (data.status === "error") { + OC.Encryption.msg.finished('#restoreBackupKeys .msg', data); + $('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false); + $('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", false); } else { - OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data); + OC.Encryption.msg.finished('#restoreBackupKeys .msg', data); } }); } }; OC.Encryption.msg={ - startDecrypting:function(selector){ + start:function(selector, msg){ var spinner = '<img src="'+ OC.imagePath('core', 'loading-small.gif') +'">'; $(selector) - .html( t('settings', 'Decrypting files... Please wait, this can take some time.') + ' ' + spinner ) + .html( msg + ' ' + spinner ) .removeClass('success') .removeClass('error') .stop(true, true) .show(); }, - finishedDecrypting:function(selector, data){ + finished:function(selector, data){ if( data.status === "success" ){ $(selector).html( data.data.message ) .addClass('success') diff --git a/settings/personal.php b/settings/personal.php index 0da14a8c8c4..47b2dc1a46a 100644 --- a/settings/personal.php +++ b/settings/personal.php @@ -33,7 +33,9 @@ $userLang=OC_Preferences::getValue( OC_User::getUser(), 'core', 'lang', OC_L10N: $languageCodes=OC_L10N::findAvailableLanguages(); //check if encryption was enabled in the past -$enableDecryptAll = OC_Util::encryptedFiles(); +$filesStillEncrypted = OC_Util::encryptedFiles(); +$backupKeysExists = OC_Util::backupKeysExists(); +$enableDecryptAll = $filesStillEncrypted || $backupKeysExists; // array of common languages $commonlangcodes = array( @@ -92,6 +94,8 @@ $tmpl->assign('passwordChangeSupported', OC_User::canUserChangePassword(OC_User: $tmpl->assign('displayNameChangeSupported', OC_User::canUserChangeDisplayName(OC_User::getUser())); $tmpl->assign('displayName', OC_User::getDisplayName()); $tmpl->assign('enableDecryptAll' , $enableDecryptAll); +$tmpl->assign('backupKeysExists' , $backupKeysExists); +$tmpl->assign('filesStillEncrypted' , $filesStillEncrypted); $tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true)); $tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser())); diff --git a/settings/routes.php b/settings/routes.php index a8bb0d981e8..21d406beeca 100644 --- a/settings/routes.php +++ b/settings/routes.php @@ -54,6 +54,10 @@ $this->create('settings_ajax_setlanguage', '/settings/ajax/setlanguage.php') ->actionInclude('settings/ajax/setlanguage.php'); $this->create('settings_ajax_decryptall', '/settings/ajax/decryptall.php') ->actionInclude('settings/ajax/decryptall.php'); +$this->create('settings_ajax_restorekeys', '/settings/ajax/restorekeys.php') + ->actionInclude('settings/ajax/restorekeys.php'); +$this->create('settings_ajax_deletekeys', '/settings/ajax/deletekeys.php') + ->actionInclude('settings/ajax/deletekeys.php'); // apps $this->create('settings_ajax_apps_ocs', '/settings/ajax/apps/ocs.php') ->actionInclude('settings/ajax/apps/ocs.php'); diff --git a/settings/templates/personal.php b/settings/templates/personal.php index cc1fce88c9f..afa3f5d700a 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -144,10 +144,15 @@ if($_['passwordChangeSupported']) { };?> <?php if($_['enableDecryptAll']): ?> -<div class="section" id="decryptAll"> +<div class="section"> + <h2> <?php p( $l->t( 'Encryption' ) ); ?> </h2> + + <?php if($_['filesStillEncrypted']): ?> + + <div id="decryptAll"> <?php p($l->t( "The encryption app is no longer enabled, please decrypt all your files" )); ?> <p> <input @@ -164,8 +169,34 @@ if($_['passwordChangeSupported']) { <span class="msg"></span> </p> <br /> + </div> + + <?php endif; ?> + + + + <div id="restoreBackupKeys" <?php $_['backupKeysExists'] ? '' : print_unescaped("class='hidden'") ?>> + + <?php p($l->t( "Your encryption keys are moved to a backup location. If something went wrong you can restore the keys. Only delete them permanently if you are sure that all files are decrypted correctly." )); ?> + <p> + <button + type="button" + name="submitRestoreKeys"><?php p($l->t( "Restore Encryption Keys" )); ?> + </button> + <button + type="button" + name="submitDeleteKeys"><?php p($l->t( "Delete Encryption Keys" )); ?> + </button> + <span class="msg"></span> + + </p> + <br /> + + </div> + + </div> -<?php endif; ?> + <?php endif; ?> <div class="section"> <h2><?php p($l->t('Version'));?></h2> |