summaryrefslogtreecommitdiffstats
path: root/apps/files_encryption
diff options
context:
space:
mode:
authorSam Tuke <samtuke@owncloud.com>2013-01-29 19:54:40 +0000
committerSam Tuke <samtuke@owncloud.com>2013-01-29 19:54:40 +0000
commitc1f20fe37a28c6f596dd55a27962d77d0ade1892 (patch)
tree9ceb64baf2b3ae2474a0c04a8967f03c7b2d3bf6 /apps/files_encryption
parent094213e23171c274e0c88fab02ad2c23d37217ce (diff)
downloadnextcloud-server-c1f20fe37a28c6f596dd55a27962d77d0ade1892.tar.gz
nextcloud-server-c1f20fe37a28c6f596dd55a27962d77d0ade1892.zip
Made encyrption keyfiles be deleted when their parents are
Made encryption keyfiles be renamed when their parents are Fixed bugs with encryptAll() execution on login
Diffstat (limited to 'apps/files_encryption')
-rw-r--r--apps/files_encryption/appinfo/spec.txt12
-rw-r--r--apps/files_encryption/hooks/hooks.php15
-rwxr-xr-xapps/files_encryption/lib/keymanager.php44
-rw-r--r--apps/files_encryption/lib/proxy.php67
-rw-r--r--apps/files_encryption/lib/util.php38
5 files changed, 142 insertions, 34 deletions
diff --git a/apps/files_encryption/appinfo/spec.txt b/apps/files_encryption/appinfo/spec.txt
index ab248be64d5..2d22dffe08d 100644
--- a/apps/files_encryption/appinfo/spec.txt
+++ b/apps/files_encryption/appinfo/spec.txt
@@ -1,3 +1,15 @@
+Encrypted files
+---------------
+
+- Each encrypted file has at least two components: the encrypted data file
+ ('catfile'), and it's corresponding key file ('keyfile'). Shared files have an
+ additional key file ('share key'). The catfile contains the encrypted data
+ concatenated with delimiter text, followed by the initialisation vector ('IV'),
+ and padding. e.g.:
+
+ [encrypted data string][delimiter][IV][padding]
+ [anhAAjAmcGXqj1X9g==][00iv00][MSHU5N5gECP7aAg7][xx] (square braces added)
+
Notes
-----
diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php
index 73d7957541a..dafa14fc000 100644
--- a/apps/files_encryption/hooks/hooks.php
+++ b/apps/files_encryption/hooks/hooks.php
@@ -37,8 +37,6 @@ class Hooks {
* @note This method should never be called for users using client side encryption
*/
public static function login( $params ) {
-
- // TODO: use lots of dependency injection here
$view = new \OC_FilesystemView( '/' );
@@ -83,8 +81,17 @@ class Hooks {
// Encrypt existing user files:
// This serves to upgrade old versions of the encryption
- // app (see appinfo/spec.txt
- $this->encryptAll( $publicKey, $this->userFilesDir, $session->getLegacyKey(), $params['password'] );
+ // app (see appinfo/spec.txt)
+ if (
+ $util->encryptAll( $publicKey, '/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'] )
+ ) {
+
+ \OC_Log::write(
+ 'Encryption library', 'Encryption of file belonging to "' . $params['uid'] . '" was started at login'
+ , \OC_Log::INFO
+ );
+
+ }
return true;
diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php
index 301e5b33fd8..8656bb96758 100755
--- a/apps/files_encryption/lib/keymanager.php
+++ b/apps/files_encryption/lib/keymanager.php
@@ -234,33 +234,33 @@ class Keymanager {
}
/**
- * @brief retrieve file encryption key
+ * @brief Delete a keyfile
*
- * @param string file name
- * @return string file key or false
+ * @param OC_FilesystemView $view
+ * @param string $userId username
+ * @param string $path path of the file the key belongs to
+ * @return bool Outcome of unlink operation
+ * @note $path must be relative to data/user/files. e.g. mydoc.txt NOT
+ * /data/admin/files/mydoc.txt
*/
- public static function deleteFileKey( $path, $staticUserClass = 'OCP\User' ) {
+ public static function deleteFileKey( \OC_FilesystemView $view, $userId, $path ) {
- $keypath = ltrim( $path, '/' );
- $user = $staticUserClass::getUser();
-
- // update $keypath and $user if path point to a file shared by someone else
-// $query = \OC_DB::prepare( "SELECT uid_owner, source, target FROM `*PREFIX*sharing` WHERE target = ? AND uid_shared_with = ?" );
-//
-// $result = $query->execute( array ('/'.$user.'/files/'.$keypath, $user));
-//
-// if ($row = $result->fetchRow()) {
-//
-// $keypath = $row['source'];
-// $keypath_parts = explode( '/', $keypath );
-// $user = $keypath_parts[1];
-// $keypath = str_replace( '/' . $user . '/files/', '', $keypath );
-//
-// }
+ $trimmed = ltrim( $path, '/' );
+ $keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed . '.key';
- $view = new \OC_FilesystemView( '/' . $user. '/files_encryption/keyfiles/' );
+ // Unlink doesn't tell us if file was deleted (not found returns
+ // true), so we perform our own test
+ if ( $view->file_exists( $keyPath ) ) {
- return $view->unlink( $keypath . '.key' );
+ return $view->unlink( $keyPath );
+
+ } else {
+
+ \OC_Log::write( 'Encryption library', 'Could not delete keyfile; does not exist: "' . $keyPath, \OC_Log::ERROR );
+
+ return false;
+
+ }
}
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index 025af3c7f14..6d2a574abd2 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -192,6 +192,73 @@ class Proxy extends \OC_FileProxy {
}
+ /**
+ * @brief When a file is deleted, remove its keyfile also
+ */
+ public function postUnlink( $path ) {
+
+ // Disable encryption proxy to prevent recursive calls
+ \OC_FileProxy::$enabled = false;
+
+ $view = new \OC_FilesystemView( '/' );
+
+ $userId = \OCP\USER::getUser();
+
+ // Format path to be relative to user files dir
+ $trimmed = ltrim( $path, '/' );
+ $split = explode( '/', $trimmed );
+ $sliced = array_slice( $split, 2 );
+ $relPath = implode( '/', $sliced );
+
+ // Delete keyfile so it isn't orphaned
+ $result = Keymanager::deleteFileKey( $view, $userId, $relPath );
+
+ \OC_FileProxy::$enabled = true;
+
+ return $result;
+
+ }
+
+ /**
+ * @brief When a file is renamed, rename its keyfile also
+ * @return bool Result of rename()
+ * @note This is pre rather than post because using post didn't work
+ */
+ public function preRename( $oldPath, $newPath ) {
+
+// trigger_error( "PATHS = ".var_export($oldPath, 1).' '.var_export($newPath, 1));
+
+ // Disable encryption proxy to prevent recursive calls
+ \OC_FileProxy::$enabled = false;
+
+ $view = new \OC_FilesystemView( '/' );
+
+ $userId = \OCP\USER::getUser();
+
+ // Format paths to be relative to user files dir
+ $oldTrimmed = ltrim( $oldPath, '/' );
+ $oldSplit = explode( '/', $oldTrimmed );
+ $oldSliced = array_slice( $oldSplit, 2 );
+ $oldRelPath = implode( '/', $oldSliced );
+ $oldKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $oldRelPath . '.key';
+
+ $newTrimmed = ltrim( $newPath, '/' );
+ $newSplit = explode( '/', $newTrimmed );
+ $newSliced = array_slice( $newSplit, 2 );
+ $newRelPath = implode( '/', $newSliced );
+ $newKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $newRelPath . '.key';
+
+// trigger_error("RENAMING = ".var_export($oldKeyfilePath, 1).' -> '.var_export($newKeyfilePath, 1));
+
+ // Rename keyfile so it isn't orphaned
+ $result = $view->rename( $oldKeyfilePath, $newKeyfilePath );
+
+ \OC_FileProxy::$enabled = true;
+
+ return $result;
+
+ }
+
public function postFopen( $path, &$result ){
if ( !$result ) {
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index fd4d7a9fcc6..2a69bba43c9 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -225,6 +225,9 @@ class Util {
* @brief Find all files and their encryption status within a directory
* @param string $directory The path of the parent directory to search
* @return mixed false if 0 found, array on success. Keys: name, path
+
+ * @note $directory needs to be a path relative to OC data dir. e.g.
+ * /admin/files NOT /backup OR /home/www/oc/data/admin/files
*/
public function findFiles( $directory ) {
@@ -293,7 +296,7 @@ class Util {
return false;
} else {
-
+
return $found;
}
@@ -334,20 +337,29 @@ class Util {
if ( $found = $this->findFiles( $dirPath ) ) {
+ // Disable proxy to prevent file being encrypted twice
+ \OC_FileProxy::$enabled = false;
+
// Encrypt unencrypted files
- foreach ( $found['plain'] as $plainFilePath ) {
-
+ foreach ( $found['plain'] as $plainFile ) {
+
// Fetch data from file
- $plainData = $this->view->file_get_contents( $plainFilePath );
+ $plainData = $this->view->file_get_contents( $plainFile['path'] );
// Encrypt data, generate catfile
$encrypted = Crypt::keyEncryptKeyfile( $plainData, $publicKey );
+ // Format path to be relative to user files dir
+ $trimmed = ltrim( $plainFile['path'], '/' );
+ $split = explode( '/', $trimmed );
+ $sliced = array_slice( $split, 2 );
+ $relPath = implode( '/', $sliced );
+
// Save catfile
- Keymanager::setFileKey( $this->view, $plainFilePath, $this->userId, $encrypted['key'] );
+ Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encrypted['key'] );
// Overwrite the existing file with the encrypted one
- $this->view->file_put_contents( $plainFilePath, $encrypted['data'] );
+ $this->view->file_put_contents( $plainFile['path'], $encrypted['data'] );
}
@@ -367,15 +379,25 @@ class Util {
$recrypted = Crypt::legacyKeyRecryptKeyfile( $legacyData, $legacyPassphrase, $publicKey, $newPassphrase );
// Save catfile
- Keymanager::setFileKey( $this->view, $plainFilePath, $this->userId, $recrypted['key'] );
+ Keymanager::setFileKey( $this->view, $plainFile['path'], $this->userId, $recrypted['key'] );
// Overwrite the existing file with the encrypted one
- $this->view->file_put_contents( $plainFilePath, $recrypted['data'] );
+ $this->view->file_put_contents( $plainFile['path'], $recrypted['data'] );
}
}
+
+ \OC_FileProxy::$enabled = true;
+
+ // If files were found, return true
+ return true;
+ } else {
+
+ // If no files were found, return false
+ return false;
+
}
}