From d95fc4e1e33f2e6fe4664d03bd39aa48f27e0ad8 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Mon, 14 Jan 2013 19:07:28 +0000 Subject: [PATCH] Adding sharing support: added new method in Keymanager setShareKey() Added notes in proxy{} and stream{} pointing to share support --- apps/files_encryption/appinfo/app.php | 16 ++++- apps/files_encryption/hooks/hooks.php | 44 ++++++++++++- apps/files_encryption/lib/keymanager.php | 77 ++++++++++++++--------- apps/files_encryption/lib/proxy.php | 9 ++- apps/files_encryption/lib/stream.php | 13 ++-- apps/files_encryption/test/keymanager.php | 16 +++-- 6 files changed, 125 insertions(+), 50 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 31b430d37a9..cc78402d1d0 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -10,10 +10,18 @@ OC::$CLASSPATH['OCA\Encryption\Session'] = 'apps/files_encryption/lib/session.ph OC_FileProxy::register( new OCA\Encryption\Proxy() ); +// User-related hooks OCP\Util::connectHook( 'OC_User','post_login', 'OCA\Encryption\Hooks', 'login' ); -OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); OCP\Util::connectHook( 'OC_User','post_setPassword','OCA\Encryption\Hooks' ,'setPassphrase' ); +// Sharing-related hooks +OCP\Util::connectHook( 'OCP\Share','post_shared','OCA\Encryption\Hooks' ,'postShared' ); +OCP\Util::connectHook( 'OCP\Share','pre_unshare','OCA\Encryption\Hooks' ,'preUnshare' ); +OCP\Util::connectHook( 'OCP\Share','pre_unshareAll','OCA\Encryption\Hooks' ,'preUnshareAll' ); + +// Webdav-related hooks +OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); + stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' ); $session = new OCA\Encryption\Session(); @@ -24,7 +32,9 @@ if ( && OCA\Encryption\Crypt::mode() == 'server' ) { - // Force the user to re-log in if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled) + // Force the user to re-log in 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.'/' ); @@ -33,5 +43,5 @@ if ( } -OCP\App::registerAdmin( 'files_encryption', 'settings'); +OCP\App::registerAdmin( 'files_encryption', 'settings' ); OCP\App::registerPersonal( 'files_encryption', 'settings-personal' ); \ No newline at end of file diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index c2f97247835..ecceae352bc 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -121,8 +121,11 @@ class Hooks { if ( isset( $params['properties']['key'] ) ) { - Keymanager::setFileKey( $params['path'], $params['properties']['key'] ); - + $view = new \OC_FilesystemView( '/' ); + $userId = \OCP\User::getUser(); + + Keymanager::setFileKey( $view, $params['path'], $userId, $params['properties']['key'] ); + } else { \OC_Log::write( @@ -138,6 +141,43 @@ class Hooks { } + /** + * @brief + */ + public static function postShared( $params ) { + + // Delete existing catfile + Keymanager::deleteFileKey( ); + + // Generate new catfile and env keys + Crypt::multiKeyEncrypt( $plainContent, $publicKeys ); + + // Save env keys to user folders + + + } + + /** + * @brief + */ + public static function preUnshare( $params ) { + + // Delete existing catfile + + // Generate new catfile and env keys + + // Save env keys to user folders + } + + /** + * @brief + */ + public static function preUnshareAll( $params ) { + + trigger_error( "preUnshareAll" ); + + } + } ?> \ No newline at end of file diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 706e1c2661e..61bc50721ef 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -238,7 +238,7 @@ class Keymanager { */ public static function setUserKeys($privatekey, $publickey) { - return (self::setPrivateKey($privatekey) && self::setPublicKey($publickey)); + return ( self::setPrivateKey( $privatekey ) && self::setPublicKey( $publickey ) ); } @@ -262,6 +262,42 @@ class Keymanager { } + /** + * @note 'shareKey' is a more user-friendly name for env_key + */ + public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) { + + $basePath = '/' . $userId . '/files_encryption/share-keys'; + + $shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId ); + + return $view->file_put_contents( $basePath . '/' . $shareKeyPath . '.shareKey', $shareKey ); + + } + + /** + * @brief Make preparations to vars and filesystem for saving a keyfile + */ + public static function keySetPreparation( \OC_FilesystemView $view, $path, $basePath, $userId ) { + + $targetPath = ltrim( $path, '/' ); + + $path_parts = pathinfo( $targetPath ); + + // If the file resides within a subdirectory, create it + if ( + isset( $path_parts['dirname'] ) + && ! $view->file_exists( $basePath . $path_parts['dirname'] ) + ) { + + $view->mkdir( $basePath . $path_parts['dirname'] ); + + } + + return $targetPath; + + } + /** * @brief store file encryption key * @@ -271,15 +307,16 @@ class Keymanager { * @note The keyfile is not encrypted here. Client code must * asymmetrically encrypt the keyfile before passing it to this method */ - public static function setFileKey( $path, $key, $view = Null, $dbClassName = '\OC_DB') { - - $targetPath = ltrim( $path, '/' ); - $user = \OCP\User::getUser(); + public static function setFileKey( \OC_FilesystemView $view, $path, $userId, $catfile ) { + + $basePath = '/' . $userId . '/files_encryption/keyfiles'; -// // update $keytarget and $user if key belongs to a file shared by someone else + $targetPath = self::keySetPreparation( $view, $path, $basePath, $userId ); + +// // update $keytarget and $userId if key belongs to a file shared by someone else // $query = $dbClassName::prepare( "SELECT uid_owner, source, target FROM `*PREFIX*sharing` WHERE target = ? AND uid_shared_with = ?" ); // -// $result = $query->execute( array ( '/'.$user.'/files/'.$targetPath, $user ) ); +// $result = $query->execute( array ( '/'.$userId.'/files/'.$targetPath, $userId ) ); // // if ( $row = $result->fetchRow( ) ) { // @@ -287,7 +324,7 @@ class Keymanager { // // $targetPath_parts = explode( '/', $targetPath ); // -// $user = $targetPath_parts[1]; +// $userId = $targetPath_parts[1]; // // $rootview = new \OC_FilesystemView( '/' ); // @@ -299,34 +336,14 @@ class Keymanager { // // } // -// $targetPath = str_replace( '/'.$user.'/files/', '', $targetPath ); +// $targetPath = str_replace( '/'.$userId.'/files/', '', $targetPath ); // // //TODO: check for write permission on shared file once the new sharing API is in place // // } - $path_parts = pathinfo( $targetPath ); - - if ( !$view ) { - - $view = new \OC_FilesystemView( '/' ); - - } - - $view->chroot( '/' . $user . '/files_encryption/keyfiles' ); - - // If the file resides within a subdirectory, create it - if ( - isset( $path_parts['dirname'] ) - && ! $view->file_exists( $path_parts['dirname'] ) - ) { - - $view->mkdir( $path_parts['dirname'] ); - - } - // Save the keyfile in parallel directory - return $view->file_put_contents( '/' . $targetPath . '.key', $key ); + return $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); } diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 52f47dba294..83c5e21c4bd 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -101,6 +101,8 @@ class Proxy extends \OC_FileProxy { // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; + # TODO: Check if file is shared, if so, use multiKeyEncrypt + // Encrypt plain data and fetch key $encrypted = Crypt::keyEncryptKeyfile( $data, Keymanager::getPublicKey( $rootView, $userId ) ); @@ -114,10 +116,11 @@ class Proxy extends \OC_FileProxy { $filePath = '/' . implode( '/', $filePath ); # TODO: make keyfile dir dynamic from app config - $view = new \OC_FilesystemView( '/' . $userId . '/files_encryption/keyfiles' ); + + $view = new \OC_FilesystemView( '/' ); // Save keyfile for newly encrypted file in parallel directory tree - Keymanager::setFileKey( $filePath, $encrypted['key'], $view, '\OC_DB' ); + Keymanager::setFileKey( $view, $filePath, $userId, $encrypted['key'] ); // Update the file cache with file info \OC_FileCache::put( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); @@ -159,6 +162,8 @@ class Proxy extends \OC_FileProxy { $userId = \OCP\USER::getUser(); + # TODO: Check if file is shared, if so, use multiKeyDecrypt + $encryptedKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ); $session = new Session(); diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index f482e2d75ac..a17a4514faa 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -302,8 +302,12 @@ class Stream { // Make sure the userId is set $this->getuser(); + # TODO: Check if file is shared, if so, use multiKeyEncrypt and + # save shareKeys in necessary user directories + // Get / generate the keyfile for the file we're handling - // If we're writing a new file (not overwriting an existing one), save the newly generated keyfile + // If we're writing a new file (not overwriting an existing + // one), save the newly generated keyfile if ( ! $this->getKey() ) { $this->keyfile = Crypt::generateKey(); @@ -312,10 +316,11 @@ class Stream { $this->encKeyfile = Crypt::keyEncrypt( $this->keyfile, $this->publicKey ); - // Save the new encrypted file key - Keymanager::setFileKey( $this->rawPath, $this->encKeyfile, new \OC_FilesystemView( '/' ) ); + $view = new \OC_FilesystemView( '/' ); + $userId = \OCP\User::getUser(); - # TODO: move this new OCFSV out of here some how, use DI + // Save the new encrypted file key + Keymanager::setFileKey( $view, $this->rawPath, $userId, $this->encKeyfile ); } diff --git a/apps/files_encryption/test/keymanager.php b/apps/files_encryption/test/keymanager.php index f02d6eb5f7a..bf453fe3163 100644 --- a/apps/files_encryption/test/keymanager.php +++ b/apps/files_encryption/test/keymanager.php @@ -79,15 +79,13 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { # NOTE: This cannot be tested until we are able to break out # of the FileSystemView data directory root -// $key = Crypt::symmetricEncryptFileContentKeyfile( $this->data, 'hat' ); -// -// $tmpPath = sys_get_temp_dir(). '/' . 'testSetFileKey'; -// -// $view = new \OC_FilesystemView( '/tmp/' ); -// -// //$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' ); -// -// Encryption\Keymanager::setFileKey( $tmpPath, $key['key'], $view ); + $key = Encryption\Crypt::symmetricEncryptFileContentKeyfile( $this->randomKey, 'hat' ); + + $path = 'unittest-'.time().'txt'; + + //$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' ); + + Encryption\Keymanager::setFileKey( $this->view, $path, $this->userId, $key['key'] ); } -- 2.39.5