diff options
author | Björn Schießle <schiessle@owncloud.com> | 2013-06-13 13:17:35 +0200 |
---|---|---|
committer | Björn Schießle <schiessle@owncloud.com> | 2013-06-13 13:17:35 +0200 |
commit | 7cfb0dc406910f66eaefc8651fd655a78883f241 (patch) | |
tree | a8cda865f793d21f8248c5035c363ee3971fdd1a /apps | |
parent | 20ddd6e1c77224d18d5be74101b80144b7187475 (diff) | |
parent | dd8011925acbd701de10e604b377c3d7f01aeff8 (diff) | |
download | nextcloud-server-7cfb0dc406910f66eaefc8651fd655a78883f241.tar.gz nextcloud-server-7cfb0dc406910f66eaefc8651fd655a78883f241.zip |
Merge branch 'master' into files_encryption_check_private_key
Conflicts:
apps/files_encryption/appinfo/app.php
apps/files_encryption/lib/util.php
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/css/files.css | 21 | ||||
-rw-r--r-- | apps/files/js/filelist.js | 2 | ||||
-rw-r--r-- | apps/files/templates/part.list.php | 4 | ||||
-rw-r--r-- | apps/files_encryption/appinfo/app.php | 61 | ||||
-rw-r--r-- | apps/files_encryption/hooks/hooks.php | 11 | ||||
-rwxr-xr-x | apps/files_encryption/lib/crypt.php | 26 | ||||
-rw-r--r-- | apps/files_encryption/lib/proxy.php | 2 | ||||
-rw-r--r-- | apps/files_encryption/lib/util.php | 106 | ||||
-rwxr-xr-x | apps/files_encryption/tests/crypt.php | 18 | ||||
-rwxr-xr-x | apps/files_encryption/tests/util.php | 31 | ||||
-rw-r--r-- | apps/files_external/ajax/addRootCertificate.php | 4 | ||||
-rw-r--r-- | apps/files_external/js/settings.js | 19 |
12 files changed, 161 insertions, 144 deletions
diff --git a/apps/files/css/files.css b/apps/files/css/files.css index f788949b1b6..108dcd741c6 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -63,8 +63,12 @@ } #filestable { position: relative; top:37px; width:100%; } tbody tr { background-color:#fff; height:2.5em; } -tbody tr:hover, tbody tr:active, tbody tr.selected { background-color:#f8f8f8; } -tbody tr.selected { background-color:#eee; } +tbody tr:hover, tbody tr:active { + background-color: rgb(240,240,240); +} +tbody tr.selected { + background-color: rgb(230,230,230); +} tbody a { color:#000; } span.extension, span.uploading, td.date { color:#999; } span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; } @@ -81,7 +85,12 @@ table th#headerDate, table td.date { min-width:11em; padding:0 .1em 0 1em; text- /* Multiselect bar */ #filestable.multiselect { top:63px; } table.multiselect thead { position:fixed; top:82px; z-index:1; -moz-box-sizing: border-box; box-sizing: border-box; left: 0; padding-left: 64px; width:100%; } -table.multiselect thead th { background:rgba(230,230,230,.8); color:#000; font-weight:bold; border-bottom:0; } +table.multiselect thead th { + background-color: rgba(210,210,210,.7); + color: #000; + font-weight: bold; + border-bottom: 0; +} table.multiselect #headerName { width: 100%; } table td.selection, table th.selection, table td.fileaction { width:2em; text-align:center; } table td.filename a.name { display:block; height:1.5em; vertical-align:middle; margin-left:3em; } @@ -115,10 +124,12 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; } } #fileList .name { position:relative; /* Firefox needs to explicitly have this default set … */ } #fileList tr:hover .fileactions { /* background to distinguish when overlaying with file names */ - background:rgba(248,248,248,.9); box-shadow:-5px 0 7px rgba(248,248,248,.9); + background-color: rgba(240,240,240,0.898); + box-shadow: -5px 0 7px rgba(240,240,240,0.898); } #fileList tr.selected:hover .fileactions, #fileList tr.mouseOver .fileactions { /* slightly darker color for selected rows */ - background:rgba(238,238,238,.9); box-shadow:-5px 0 7px rgba(238,238,238,.9); + background-color: rgba(230,230,230,.9); + box-shadow: -5px 0 7px rgba(230,230,230,.9); } #fileList .fileactions a.action img { position:relative; top:.2em; } #fileList a.action { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index c24d1fd8244..e19a35bbc5b 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -51,7 +51,7 @@ var FileList={ }else{ simpleSize=t('files', 'Pending'); } - var sizeColor = Math.round(200-Math.pow((size/(1024*1024)),2)); + var sizeColor = Math.round(160-Math.pow((size/(1024*1024)),2)); var lastModifiedTime = Math.round(lastModified.getTime() / 1000); td = $('<td></td>').attr({ "class": "filesize", diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index 1719d25e660..1e94275dcba 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -3,12 +3,12 @@ <?php foreach($_['files'] as $file): $simple_file_size = OCP\simple_file_size($file['size']); // the bigger the file, the darker the shade of grey; megabytes*2 - $simple_size_color = intval(200-$file['size']/(1024*1024)*2); + $simple_size_color = intval(160-$file['size']/(1024*1024)*2); if($simple_size_color<0) $simple_size_color = 0; $relative_modified_date = OCP\relative_modified_date($file['mtime']); // the older the file, the brighter the shade of grey; days*14 $relative_date_color = round((time()-$file['mtime'])/60/60/24*14); - if($relative_date_color>200) $relative_date_color = 200; + if($relative_date_color>160) $relative_date_color = 160; $name = rawurlencode($file['name']); $name = str_replace('%2F', '/', $name); $directory = rawurlencode($file['directory']); diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 6e68d81ba00..419bef1edef 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -10,46 +10,51 @@ OC::$CLASSPATH['OCA\Encryption\Session'] = 'files_encryption/lib/session.php'; OC::$CLASSPATH['OCA\Encryption\Capabilities'] = 'files_encryption/lib/capabilities.php'; OC::$CLASSPATH['OCA\Encryption\Helper'] = 'files_encryption/lib/helper.php'; -OC_FileProxy::register(new OCA\Encryption\Proxy()); +if (!OC_Config::getValue('maintenance', false)) { + OC_FileProxy::register(new OCA\Encryption\Proxy()); -// User related hooks -OCA\Encryption\Helper::registerUserHooks(); + // User related hooks + OCA\Encryption\Helper::registerUserHooks(); -// Sharing related hooks -OCA\Encryption\Helper::registerShareHooks(); + // Sharing related hooks + OCA\Encryption\Helper::registerShareHooks(); -// Filesystem related hooks -OCA\Encryption\Helper::registerFilesystemHooks(); + // Filesystem related hooks + OCA\Encryption\Helper::registerFilesystemHooks(); -stream_wrapper_register('crypt', 'OCA\Encryption\Stream'); + stream_wrapper_register('crypt', 'OCA\Encryption\Stream'); -// check if we are logged in -if (OCP\User::isLoggedIn()) { + // check if we are logged in + if (OCP\User::isLoggedIn()) { - // ensure filesystem is loaded - if(!\OC\Files\Filesystem::$loaded) { - \OC_Util::setupFS(); - } + // ensure filesystem is loaded + if (!\OC\Files\Filesystem::$loaded) { + \OC_Util::setupFS(); + } - $view = new OC_FilesystemView('/'); - $session = new \OCA\Encryption\Session($view); + $view = new OC_FilesystemView('/'); + $session = new \OCA\Encryption\Session($view); - $user = \OCP\USER::getUser(); - // check if user has a private key - if ( - !$view->file_exists('/' . $user . '/files_encryption/' . $user . '.private.key') - && OCA\Encryption\Crypt::mode() === 'server' - ) { + $user = \OCP\USER::getUser(); + // check if user has a private key + if ( + !$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(); + // 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 . '/'); + header("Location: " . OC::$WEBROOT . '/'); - exit(); + exit(); + } } +} else { + // logout user if we are in maintenance to force re-login + OCP\User::logout(); } // Register settings scripts diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 4434df8f147..7698b95cfd3 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -72,10 +72,13 @@ class Hooks { $session->setPrivateKey($privateKey);
// Check if first-run file migration has already been performed
- $migrationCompleted = $util->getMigrationStatus();
+ $ready = false;
+ if ($util->getMigrationStatus() === Util::MIGRATION_OPEN) {
+ $ready = $util->beginMigration();
+ }
// If migration not yet done
- if (!$migrationCompleted) {
+ if ($ready) {
$userView = new \OC_FilesystemView('/' . $params['uid']);
@@ -86,7 +89,7 @@ class Hooks { && $encLegacyKey = $userView->file_get_contents('encryption.key')
) {
- $plainLegacyKey = Crypt::legacyBlockDecrypt($encLegacyKey, $params['password']);
+ $plainLegacyKey = Crypt::legacyDecrypt($encLegacyKey, $params['password']);
$session->setLegacyKey($plainLegacyKey);
@@ -107,7 +110,7 @@ class Hooks { }
// Register successful migration in DB
- $util->setMigrationStatus(1);
+ $util->finishMigration();
}
diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index ecbec2e8b2b..cd41390d1c5 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -636,7 +636,7 @@ class Crypt { *
* This function decrypts an content
*/
- private static function legacyDecrypt($content, $passphrase = '') {
+ public static function legacyDecrypt($content, $passphrase = '') {
$bf = self::getBlowfish($passphrase);
@@ -665,28 +665,4 @@ class Crypt { }
}
- /**
- * @param $legacyEncryptedContent
- * @param $legacyPassphrase
- * @param $publicKeys
- * @return array
- */
- public static function legacyKeyRecryptKeyfile($legacyEncryptedContent, $legacyPassphrase, $publicKeys) {
-
- $decrypted = self::legacyBlockDecrypt($legacyEncryptedContent, $legacyPassphrase);
-
- // Encrypt plain data, generate keyfile & encrypted file
- $cryptedData = self::symmetricEncryptFileContentKeyfile($decrypted);
-
- // Encrypt plain keyfile to multiple sharefiles
- $multiEncrypted = Crypt::multiKeyEncrypt($cryptedData['key'], $publicKeys);
-
- return array(
- 'data' => $cryptedData['encrypted'],
- 'filekey' => $multiEncrypted['data'],
- 'sharekeys' => $multiEncrypted['keys']
- );
-
- }
-
}
\ No newline at end of file diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 0df34a38bd7..735eba911a9 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -256,6 +256,8 @@ class Proxy extends \OC_FileProxy { */ public function postFopen($path, &$result) { + $path = \OC\Files\Filesystem::normalizePath($path); + if (!$result) { return $result; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index d5a5ce774d2..94defa726a9 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -96,10 +96,13 @@ class Util { //// DONE: test new encryption with sharing //// TODO: test new encryption with proxies + const MIGRATION_COMPLETED = 1; // migration to new encryption completed + const MIGRATION_IN_PROGRESS = -1; // migration is running + const MIGRATION_OPEN = 0; // user still needs to be migrated + private $view; // OC_FilesystemView object for filesystem operations private $userId; // ID of the currently logged-in user - private $pwd; // User Password private $client; // Client side encryption mode flag private $publicKeyDir; // Dir containing all public user keys private $encryptionDir; // Dir containing user's files_encryption @@ -728,40 +731,28 @@ class Util { // Fetch data from file $legacyData = $this->view->file_get_contents($legacyFile['path']); - $sharingEnabled = \OCP\Share::isEnabled(); - - // if file exists try to get sharing users - if ($this->view->file_exists($legacyFile['path'])) { - $uniqueUserIds = $this->getSharingUsersArray($sharingEnabled, $legacyFile['path'], $this->userId); - } else { - $uniqueUserIds[] = $this->userId; - } - - // Fetch public keys for all users who will share the file - $publicKeys = Keymanager::getPublicKeys($this->view, $uniqueUserIds); - - // Recrypt data, generate catfile - $recrypted = Crypt::legacyKeyRecryptKeyfile($legacyData, $legacyPassphrase, $publicKeys); + // decrypt data, generate catfile + $decrypted = Crypt::legacyBlockDecrypt($legacyData, $legacyPassphrase); $rawPath = $legacyFile['path']; - $relPath = \OCA\Encryption\Helper::stripUserFilesPath($rawPath); - // Save keyfile - Keymanager::setFileKey($this->view, $relPath, $this->userId, $recrypted['filekey']); + // enable proxy the ensure encryption is handled + \OC_FileProxy::$enabled = true; + + // Open enc file handle for binary writing, with same filename as original plain file + $encHandle = $this->view->fopen( $rawPath, 'wb' ); - // Save sharekeys to user folders - Keymanager::setShareKeys($this->view, $relPath, $recrypted['sharekeys']); + if (is_resource($encHandle)) { - // Overwrite the existing file with the encrypted one - $this->view->file_put_contents($rawPath, $recrypted['data']); + // write data to stream + fwrite($encHandle, $decrypted); - $size = strlen($recrypted['data']); + // close stream + fclose($encHandle); + } - // Add the file to the cache - \OC\Files\Filesystem::putFileInfo($rawPath, array( - 'encrypted' => true, - 'size' => $size - ), ''); + // disable proxy to prevent file being encrypted twice + \OC_FileProxy::$enabled = false; } } @@ -1060,36 +1051,56 @@ class Util { } /** - * @brief Set file migration status for user - * @param $status - * @return bool + * @brief start migration mode to initially encrypt users data + * @return boolean */ - public function setMigrationStatus($status) { - - $sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ?'; + public function beginMigration() { - $args = array( - $status, - $this->userId - ); + $return = false; + $sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ? and `migration_status` = ?'; + $args = array(self::MIGRATION_IN_PROGRESS, $this->userId, self::MIGRATION_OPEN); $query = \OCP\DB::prepare($sql); + $result = $query->execute($args); + $manipulatedRows = $result->numRows(); - if ($query->execute($args)) { + if ($manipulatedRows === 1) { + $return = true; + \OCP\Util::writeLog('Encryption library', "Start migration to encryption mode for " . $this->userId, \OCP\Util::INFO); + } else { + \OCP\Util::writeLog('Encryption library', "Could not activate migration mode for " . $this->userId . ". Probably another process already started the initial encryption", \OCP\Util::WARN); + } - return true; + return $return; + } - } else { + /** + * @brief close migration mode after users data has been encrypted successfully + * @return boolean + */ + public function finishMigration() { - return false; + $return = false; + + $sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ? and `migration_status` = ?'; + $args = array(self::MIGRATION_COMPLETED, $this->userId, self::MIGRATION_IN_PROGRESS); + $query = \OCP\DB::prepare($sql); + $result = $query->execute($args); + $manipulatedRows = $result->numRows(); + if ($manipulatedRows === 1) { + $return = true; + \OCP\Util::writeLog('Encryption library', "Finish migration successfully for " . $this->userId, \OCP\Util::INFO); + } else { + \OCP\Util::writeLog('Encryption library', "Could not deactivate migration mode for " . $this->userId, \OCP\Util::WARN); } + return $return; } /** - * @brief Check whether pwd recovery is enabled for a given user - * @return bool 1 = yes, 0 = no, false = no record + * @brief check if files are already migrated to the encryption system + * @return migration status, false = in case of no record * @note If records are not being returned, check for a hidden space * at the start of the uid in db */ @@ -1118,14 +1129,11 @@ class Util { // If no record is found if (empty($migrationStatus)) { - + \OCP\Util::writeLog('Encryption library', "Could not get migration status for " . $this->userId . ", no record found", \OCP\Util::ERROR); return false; - // If a record is found } else { - - return $migrationStatus[0]; - + return (int)$migrationStatus[0]; } } diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index e6ea3bcd6b3..9b97df22d16 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -629,24 +629,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test decryption using legacy blowfish method - * @depends testLegacyEncryptLong - */ - function testLegacyKeyRecryptKeyfileEncrypt($crypted) { - - $recrypted = Encryption\Crypt::LegacyKeyRecryptKeyfile($crypted, $this->pass, array($this->genPublicKey)); - - $this->assertNotEquals($this->dataLong, $recrypted['data']); - - return $recrypted; - - # TODO: search inencrypted text for actual content to ensure it - # genuine transformation - - } - - /** - * @medium */ function testRenameFile() { diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index 6d6c8bca3dd..cb10befc8e4 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -75,7 +75,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $this->legacyData = realpath(dirname(__FILE__) . '/legacy-text.txt'); $this->legacyEncryptedData = realpath(dirname(__FILE__) . '/legacy-encrypted-text.txt'); $this->legacyEncryptedDataKey = realpath(dirname(__FILE__) . '/encryption.key'); - $this->legacyKey = '30943623843030686906'; + $this->legacyKey = "30943623843030686906\0\0\0\0"; $keypair = Encryption\Crypt::createKeypair(); @@ -182,8 +182,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $params['uid'] = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER; $params['password'] = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER; - $util = new Encryption\Util($this->view, \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); - $util->setMigrationStatus(0); + $this->setMigrationStatus(0, \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); $this->assertTrue(OCA\Encryption\Hooks::login($params)); @@ -285,7 +284,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $params['password'] = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER; $util = new Encryption\Util($this->view, \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); - $util->setMigrationStatus(0); + $this->setMigrationStatus(0, \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); $this->assertTrue(OCA\Encryption\Hooks::login($params)); @@ -330,4 +329,28 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $params['password'] = $password; OCA\Encryption\Hooks::login($params); } + + /** + * helper function to set migration status to the right value + * to be able to test the migration path + * + * @param $status needed migration status for test + * @param $user for which user the status should be set + * @return boolean + */ + private function setMigrationStatus($status, $user) { + $sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ?'; + $args = array( + $status, + $user + ); + + $query = \OCP\DB::prepare($sql); + if ($query->execute($args)) { + return true; + } else { + return false; + } + } + } diff --git a/apps/files_external/ajax/addRootCertificate.php b/apps/files_external/ajax/addRootCertificate.php index 43fd6752c4a..ae349bfcd3a 100644 --- a/apps/files_external/ajax/addRootCertificate.php +++ b/apps/files_external/ajax/addRootCertificate.php @@ -29,8 +29,12 @@ if ($isValid == false) { // add the certificate if it could be verified if ( $isValid ) { + // disable proxy to prevent multiple fopen calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; $view->file_put_contents($filename, $data); OC_Mount_Config::createCertificateBundle(); + \OC_FileProxy::$enabled = $proxyStatus; } else { OCP\Util::writeLog('files_external', 'Couldn\'t import SSL root certificate ('.$filename.'), allowed formats: PEM and DER', diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index ac408786ff6..3e605c59a93 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -88,7 +88,7 @@ OC.MountConfig={ url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), data: { mountPoint: mountPoint, - class: backendClass, + 'class': backendClass, classOptions: classOptions, mountType: mountType, applicable: applicable, @@ -103,7 +103,7 @@ OC.MountConfig={ url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), data: { mountPoint: mountPoint, - class: backendClass, + 'class': backendClass, classOptions: classOptions, mountType: mountType, applicable: applicable, @@ -247,15 +247,18 @@ $(document).ready(function() { OC.MountConfig.saveStorage($(this).parent().parent()); }); + $('#sslCertificate').on('click', 'td.remove>img', function() { + var $tr = $(this).parent().parent(); + var row = this.parentNode.parentNode; + $.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: row.id}); + $tr.remove(); + return true; + }); + $('#externalStorage').on('click', 'td.remove>img', function() { var tr = $(this).parent().parent(); var mountPoint = $(tr).find('.mountPoint input').val(); - if ( ! mountPoint) { - var row=this.parentNode.parentNode; - $.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), { cert: row.id }); - $(tr).remove(); - return true; - } + if ($('#externalStorage').data('admin') === true) { var isPersonal = false; var multiselect = $(tr).find('.chzn-select').val(); |