From b3e59ca1e31f162d7ac720d8729958f438b23a02 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Sat, 9 Feb 2013 18:39:32 +0000 Subject: Work on post_share hook for files_encryption New method in OCP\Share{}:: getUsersSharingFile() Development shapshot --- lib/public/share.php | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'lib') diff --git a/lib/public/share.php b/lib/public/share.php index af2a538e252..936f85021c0 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -91,6 +91,60 @@ class Share { } return false; } + + /** + * @brief Find which users can access a shared item + * @param string Item type + * @param int Format (optional) Format type must be defined by the backend + * @param int Number of items to return (optional) Returns all by default + * @return Return depends on format + */ + public static function getUsersSharingFile( $path ) { + + // Fetch all shares of this file path from DB + $query = \OC_DB::prepare( + 'SELECT + share_type + , share_with + , permissions + FROM + `*PREFIX*share` + WHERE + file_target = ?' + ); + + $result = $query->execute( array( $path ) ); + + if ( \OC_DB::isError( $result ) ) { + + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $path, \OC_Log::ERROR ); + + } + + $shares = array(); + + while( $row = $result->fetchRow() ) { + + // Set helpful array keys + $shares[] = array( + 'userId' => $row['share_with'] + , 'shareType' => $row['share_type'] + , 'permissions' => $row['permissions'] + ); + + } + + if ( ! empty( $shares ) ) { + + return $shares; + + } else { + + return false; + + } + + } /** * @brief Get the items of item type shared with the current user -- cgit v1.2.3 From 92f06243be62945b5ff5e7542e9984f7bb45d74b Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Mon, 11 Feb 2013 10:21:23 +0000 Subject: Implementing sharing support New file-specific methods in lib/public/share Changes to how keyfiles are stored --- apps/files_encryption/hooks/hooks.php | 47 +++++++------ apps/files_encryption/lib/crypt.php | 41 ++++++++--- apps/files_encryption/lib/keymanager.php | 97 +++++++++++++++++++++++--- apps/files_encryption/lib/proxy.php | 113 +++++++++++++++++-------------- apps/files_encryption/test/crypt.php | 8 +-- lib/public/share.php | 82 ++++++++++++++++++++-- 6 files changed, 283 insertions(+), 105 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index c6d4c16115a..9252a341fb7 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -82,8 +82,12 @@ class Hooks { } + \OC_FileProxy::$enabled = false; + $publicKey = Keymanager::getPublicKey( $view, $params['uid'] ); + \OC_FileProxy::$enabled = false; + // Encrypt existing user files: // This serves to upgrade old versions of the encryption // app (see appinfo/spec.txt) @@ -175,8 +179,9 @@ class Hooks { $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); + $session = new Session(); - $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'] ); + $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 ); $userIds = array(); @@ -202,41 +207,35 @@ class Hooks { } - trigger_error("UIDS = ".var_export($userIds, 1)); - $userPubKeys = Keymanager::getPublicKeys( $view, $userIds ); -// trigger_error("PUB KEYS = ".var_export($userPubKeys, 1)); - - // TODO: Fetch path from Crypt{} getter - $plainContent = $view->file_get_contents( $userId . '/' . 'files'. '/' . $params['fileTarget'] ); + \OC_FileProxy::$enabled = false; - // Generate new catfile and share keys - if ( ! $encrypted = Crypt::multiKeyEncrypt( $plainContent, $userPubKeys ) ) { + // get the keyfile + $encKeyfile = Keymanager::getFileKey( $view, $userId, $params['fileTarget'] ); - // If the re-encryption failed, don't risk deleting data - return false; - - } + $privateKey = $session->getPrivateKey(); - trigger_error("ENCRYPTED = ". var_export($encrypted, 1)); + // decrypt the keyfile + $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); - // Save env keys to user folders - foreach ( $encrypted['keys'] as $key ) { + // re-enc keyfile to sharekeys + $shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); -// Keymanager::setShareKey( $view, $params['fileTarget'], $userId, $key ); + // save sharekeys + if ( ! Keymanager::setShareKeys( $view, $params['fileTarget'], $shareKeys['keys'] ) ) { + trigger_error( "SET Share keys failed" ); + } - // Delete existing catfile - // Check if keyfile exists (it won't if file has been shared before) + // Delete existing keyfile // Do this last to ensure file is recoverable in case of error - if ( $util->isEncryptedPath( $params['fileTarget'] ) ) { - - // NOTE: This will trigger an error if keyfile isn't found -// Keymanager::deleteFileKey( $params['fileTarget'] ); +// Keymanager::deleteFileKey( $view, $userId, $params['fileTarget'] ); - } + \OC_FileProxy::$enabled = true; + + return true; } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index e3d23023db3..fdee03eeaf5 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -370,22 +370,41 @@ class Crypt { /** * @brief Create asymmetrically encrypted keyfile content using a generated key * @param string $plainContent content to be encrypted - * @returns array keys: key, encrypted - * @note symmetricDecryptFileContent() can be used to decrypt files created using this method - * - * This function decrypts a file + * @param array $publicKeys array keys must be the userId of corresponding user + * @returns array keys: keys (array, key = userId), encrypted + * @note symmetricDecryptFileContent() can decrypt files created using this method */ public static function multiKeyEncrypt( $plainContent, array $publicKeys ) { - + + // openssl_seal returns false without errors if $plainContent + // is empty, so trigger our own error + if ( empty( $plainContent ) ) { + + trigger_error( "Cannot mutliKeyEncrypt empty plain content" ); + throw new \Exception( 'Cannot mutliKeyEncrypt empty plain content' ); + + } + // Set empty vars to be set by openssl by reference $sealed = ''; - $envKeys = array(); + $shareKeys = array(); - if( openssl_seal( $plainContent, $sealed, $envKeys, $publicKeys ) ) { + if( openssl_seal( $plainContent, $sealed, $shareKeys, $publicKeys ) ) { + + $i = 0; + + // Ensure each shareKey is labelled with its + // corresponding userId + foreach ( $publicKeys as $userId => $publicKey ) { + + $mappedShareKeys[$userId] = $shareKeys[$i]; + $i++; + + } return array( - 'keys' => $envKeys - , 'encrypted' => $sealed + 'keys' => $mappedShareKeys + , 'data' => $sealed ); } else { @@ -404,7 +423,7 @@ class Crypt { * * This function decrypts a file */ - public static function multiKeyDecrypt( $encryptedContent, $envKey, $privateKey ) { + public static function multiKeyDecrypt( $encryptedContent, $shareKey, $privateKey ) { if ( !$encryptedContent ) { @@ -412,7 +431,7 @@ class Crypt { } - if ( openssl_open( $encryptedContent, $plainContent, $envKey, $privateKey ) ) { + if ( openssl_open( $encryptedContent, $plainContent, $shareKey, $privateKey ) ) { return $plainContent; diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 3160572ba1b..5f9eea1a0bc 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -52,8 +52,11 @@ class Keymanager { */ public static function getPublicKey( \OC_FilesystemView $view, $userId ) { + \OC_FileProxy::$enabled = false; + return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); + \OC_FileProxy::$enabled = true; } /** @@ -77,20 +80,16 @@ class Keymanager { * @param array $userIds * @return array of public keys for the specified users */ - public static function getPublicKeys( \OC_FilesystemView $view, $userIds ) { + public static function getPublicKeys( \OC_FilesystemView $view, array $userIds ) { - $i = 0; $keys = array(); foreach ( $userIds as $userId ) { - $i++; $keys[$userId] = self::getPublicKey( $view, $userId ); } - $keys['total'] = $i; - return $keys; } @@ -137,11 +136,11 @@ class Keymanager { $filePath_f = ltrim( $filePath, '/' ); - $catfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + $keyfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; - if ( $view->file_exists( $catfilePath ) ) { + if ( $view->file_exists( $keyfilePath ) ) { - return $view->file_get_contents( $catfilePath ); + return $view->file_get_contents( $keyfilePath ); } else { @@ -239,7 +238,7 @@ class Keymanager { } /** - * @brief store file encryption key + * @brief store share key * * @param string $path relative path of the file, including filename * @param string $key @@ -255,7 +254,85 @@ class Keymanager { $shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId ); - return $view->file_put_contents( $basePath . '/' . $shareKeyPath . '.shareKey', $shareKey ); + $writePath = $basePath . '/' . $shareKeyPath . '.shareKey'; + + \OC_FileProxy::$enabled = false; + + $result = $view->file_put_contents( $writePath, $shareKey ); + + if ( + is_int( $result ) + && $result > 0 + ) { + + return true; + + } else { + + return false; + + } + + } + + /** + * @brief store multiple share keys for a single file + * @return bool + */ + public static function setShareKeys( \OC_FilesystemView $view, $path, array $shareKeys ) { + + // $shareKeys must be an array with the following format: + // [userId] => [encrypted key] + + $result = true; + + foreach ( $shareKeys as $userId => $shareKey ) { + + if ( ! self::setShareKey( $view, $path, $userId, $shareKey ) ) { + + // If any of the keys are not set, flag false + $result = false; + + } + + } + + // Returns false if any of the keys weren't set + return $result; + + } + + /** + * @brief retrieve shareKey for an encrypted file + * @param \OC_FilesystemView $view + * @param $userId + * @param $filePath + * @internal param \OCA\Encryption\file $string name + * @return string file key or false + * @note The sharekey returned is encrypted. Decryption + * of the keyfile must be performed by client code + */ + public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) { + + \OC_FileProxy::$enabled = false; + + $filePath_f = ltrim( $filePath, '/' ); + + $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $filePath_f . '.shareKey'; + + if ( $view->file_exists( $shareKeyPath ) ) { + + $result = $view->file_get_contents( $shareKeyPath ); + + } else { + + $result = false; + + } + + \OC_FileProxy::$enabled = true; + + return $result; } diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 58b9bc0725b..b5e59e89b9e 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -99,58 +99,65 @@ class Proxy extends \OC_FileProxy { if ( !is_resource( $data ) ) { $userId = \OCP\USER::getUser(); - $rootView = new \OC_FilesystemView( '/' ); - + $util = new Util( $rootView, $userId ); + $filePath = $util->stripUserFilesPath( $path ); // Set the filesize for userland, before encrypting $size = strlen( $data ); // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; - $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + // Encrypt data + $encData = Crypt::symmetricEncryptFileContentKeyfile( $data ); // Check if the keyfile needs to be shared - if ( - $fileOwner !== true - or $fileOwner !== $userId - ) { + if ( \OCP\Share::isSharedFile( $filePath ) ) { + +// $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + + // List everyone sharing the file + $shares = \OCP\Share::getUsersSharingFile( $filePath, 1 ); + + $userIds = array(); + + foreach ( $shares as $share ) { + + $userIds[] = $share['userId']; + + } + + $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); + + \OC_FileProxy::$enabled = false; + + // Encrypt plain keyfile to multiple sharefiles + $multiEncrypted = Crypt::multiKeyEncrypt( $encData['key'], $publicKeys ); + + // Save sharekeys to user folders + Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); + + // Set encrypted keyfile as common varname + $encKey = $multiEncrypted['encrypted']; - // Shared storage backend isn't loaded - $users = \OCP\Share::getItemShared( 'file', $path, \OC_Share_backend_File::FORMAT_SHARED_STORAGE ); -// - trigger_error("SHARE USERS = ". var_export($users, 1)); -// -// $publicKeys = Keymanager::getPublicKeys( $rootView, $users); -// -// // Encrypt plain data to multiple users -// $encrypted = Crypt::multiKeyEncrypt( $data, $publicKeys ); } else { $publicKey = Keymanager::getPublicKey( $rootView, $userId ); // Encrypt plain data to a single user - $encrypted = Crypt::keyEncryptKeyfile( $data, $publicKey ); + $encKey = Crypt::keyEncrypt( $encData['key'], $publicKey ); } - // Replace plain content with encrypted content by reference - $data = $encrypted['data']; - - $filePath = explode( '/', $path ); - - $filePath = array_slice( $filePath, 3 ); - - $filePath = '/' . implode( '/', $filePath ); - - // TODO: make keyfile dir dynamic from app config - - $view = new \OC_FilesystemView( '/' ); + // TODO: Replace userID with ownerId so keyfile is saved centrally // Save keyfile for newly encrypted file in parallel directory tree - Keymanager::setFileKey( $view, $filePath, $userId, $encrypted['key'] ); + Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey ); + + // Replace plain content with encrypted content by reference + $data = $encData['encrypted']; // Update the file cache with file info \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); @@ -168,8 +175,6 @@ class Proxy extends \OC_FileProxy { * @param string $data Data that has been read from file */ public function postFile_get_contents( $path, $data ) { - - // TODO: Use dependency injection to add required args for view and user etc. to this method // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; @@ -180,45 +185,55 @@ class Proxy extends \OC_FileProxy { && Crypt::isCatfile( $data ) ) { - $split = explode( '/', $path ); - - $filePath = array_slice( $split, 3 ); + $view = new \OC_FilesystemView( '/' ); + $userId = \OCP\USER::getUser(); + $session = new Session(); + $util = new Util( $view, $userId ); + $filePath = $util->stripUserFilesPath( $path ); + $privateKey = $session->getPrivateKey( $userId ); - $filePath = '/' . implode( '/', $filePath ); + // Get the encrypted keyfile + $encKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ); - //$cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); + // Check if key is shared or not + if ( \OCP\Share::isSharedFile( $filePath ) ) { - $view = new \OC_FilesystemView( '' ); + // If key is shared, fetch the user's shareKey + $shareKey = Keymanager::getShareKey( $view, $userId, $filePath ); + + \OC_FileProxy::$enabled = false; + + // Decrypt keyfile with shareKey + $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); - $userId = \OCP\USER::getUser(); + } else { + + // If key is unshared, decrypt with user private key + $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); - // TODO: Check if file is shared, if so, use multiKeyDecrypt + } - $encryptedKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ); + $plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile ); - $session = new Session(); - - $decrypted = Crypt::keyDecryptKeyfile( $data, $encryptedKeyfile, $session->getPrivateKey( $split[1] ) ); - } elseif ( Crypt::mode() == 'server' && isset( $_SESSION['legacyenckey'] ) && Crypt::isEncryptedMeta( $path ) ) { - $decrypted = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] ); + $plainData = Crypt::legacyDecrypt( $data, $session->getLegacyKey() ); } \OC_FileProxy::$enabled = true; - if ( ! isset( $decrypted ) ) { + if ( ! isset( $plainData ) ) { - $decrypted = $data; + $plainData = $data; } - return $decrypted; + return $plainData; } diff --git a/apps/files_encryption/test/crypt.php b/apps/files_encryption/test/crypt.php index aa87ec32821..48ad2ee0075 100755 --- a/apps/files_encryption/test/crypt.php +++ b/apps/files_encryption/test/crypt.php @@ -439,14 +439,14 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $this->assertTrue( strlen( $pair1['privateKey'] ) > 1 ); - $crypted = Encryption\Crypt::multiKeyEncrypt( $this->dataUrl, array( $pair1['publicKey'] ) ); + $crypted = Encryption\Crypt::multiKeyEncrypt( $this->dataShort, array( $pair1['publicKey'] ) ); - $this->assertNotEquals( $this->dataUrl, $crypted['encrypted'] ); + $this->assertNotEquals( $this->dataShort, $crypted['data'] ); - $decrypt = Encryption\Crypt::multiKeyDecrypt( $crypted['encrypted'], $crypted['keys'][0], $pair1['privateKey'] ); + $decrypt = Encryption\Crypt::multiKeyDecrypt( $crypted['data'], $crypted['keys'][0], $pair1['privateKey'] ); - $this->assertEquals( $this->dataUrl, $decrypt ); + $this->assertEquals( $this->dataShort, $decrypt ); } diff --git a/lib/public/share.php b/lib/public/share.php index 936f85021c0..4170783d71e 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -92,20 +92,73 @@ class Share { return false; } + /** + * @brief Prepare a path to be passed to DB as file_target + * @return string Prepared path + */ + public static function prepFileTarget( $path ) { + + // Paths in DB are stored with leading slashes, so add one if necessary + if ( substr( $path, 0, 1 ) !== '/' ) { + + $path = '/' . $path; + + } + + return $path; + + } + + public static function isSharedFile( $path ) { + + $fPath = self::prepFileTarget( $path ); + + // Fetch all shares of this file path from DB + $query = \OC_DB::prepare( + 'SELECT + id + FROM + `*PREFIX*share` + WHERE + file_target = ?' + ); + + $result = $query->execute( array( $fPath ) ); + + if ( \OC_DB::isError( $result ) ) { + + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage( $result ) . ', path=' . $fPath, \OC_Log::ERROR ); + + } + + if ( $result->fetchRow() !== false ) { + + return true; + + } else { + + return false; + + } + + } + /** * @brief Find which users can access a shared item - * @param string Item type - * @param int Format (optional) Format type must be defined by the backend - * @param int Number of items to return (optional) Returns all by default - * @return Return depends on format + * @return bool / array + * @note $path needs to be relative to user data dir, e.g. 'file.txt' + * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path ) { + public static function getUsersSharingFile( $path, $includeOwner = 0 ) { + + $fPath = self::prepFileTarget( $path ); // Fetch all shares of this file path from DB $query = \OC_DB::prepare( 'SELECT share_type , share_with + , uid_owner , permissions FROM `*PREFIX*share` @@ -113,11 +166,11 @@ class Share { file_target = ?' ); - $result = $query->execute( array( $path ) ); + $result = $query->execute( array( $fPath ) ); if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $path, \OC_Log::ERROR ); + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $fPath, \OC_Log::ERROR ); } @@ -128,6 +181,7 @@ class Share { // Set helpful array keys $shares[] = array( 'userId' => $row['share_with'] + , 'owner' => $row['uid_owner'] // we just set this so it can be used once, hugly hack :/ , 'shareType' => $row['share_type'] , 'permissions' => $row['permissions'] ); @@ -136,6 +190,20 @@ class Share { if ( ! empty( $shares ) ) { + // Include owner in list of users, if requested + if ( $includeOwner == 1 ) { + + // NOTE: The values are incorrect for shareType and + // permissions of the owner; we just include them for + // optional convenience + $shares[] = array( + 'userId' => $shares[0]['owner'] + , 'shareType' => 0 + , 'permissions' => 0 + ); + + } + return $shares; } else { -- cgit v1.2.3 From 8eef919a754ff3404df1065d616e66cb9b1ff437 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Tue, 12 Feb 2013 12:08:34 +0100 Subject: take group shares into account if we retrieve the list a all recipients --- apps/files_encryption/hooks/hooks.php | 35 ++++--------------- apps/files_encryption/lib/crypt.php | 30 ++++++++++++++-- lib/public/share.php | 65 ++++++++++++++++------------------- 3 files changed, 63 insertions(+), 67 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 17bcb9238ac..c14ce3e91db 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -167,44 +167,21 @@ class Hooks { * @brief */ public static function postShared( $params ) { - error_log("post shared triggered!"); + // NOTE: $params is an array with these keys: // itemSource -> int, filecache file ID // shareWith -> string, uid of user being shared to // fileTarget -> path of file being shared // uidOwner -> owner of the original file being shared + //TODO: We don't deal with shared folder yet, need to recursively update every file in the folder + $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); - $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 ); - - $userIds = array(); - - foreach ( $shares as $share ) { - - $util = new Util( $view, $share['userId'] ); - - // Check that the user is encryption capable - // TODO create encryption key when user gets created - if ( $util->ready() ) { - - // Construct array of just UIDs for Keymanager{} - $userIds[] = $share['userId']; - - } else { - - // Log warning; we can't do necessary setup here - // because we don't have the user passphrase - // TODO: Provide user feedback indicating that - // sharing failed - \OC_Log::write( 'Encryption library', 'File cannot be shared: user "'.$share['userId'].'" is not setup for encryption', \OC_Log::WARN ); - - } + $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); - } - return Crypt::encKeyfileToMultipleUsers($shares, $params['fileTarget']); } @@ -213,11 +190,11 @@ class Hooks { * @brief */ public static function preUnshare( $params ) { - $items = \OCP\Share::getItemSharedWithBySource($params['itemType'], $params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $item[0]['file_target'], 1 ); + $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); $userIds = array(); foreach ( $shares as $share ) { + error_log("keek user id: " . $share['userId']); $userIds[] = $share['userId']; } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 6704ea6bf18..a8cc2b3726d 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -752,16 +752,40 @@ class Crypt { */ public static function encKeyfileToMultipleUsers($users, $fileTarget) { $view = new \OC_FilesystemView( '/' ); - $userId = \OCP\User::getUser(); + $owner = \OCP\User::getUser(); $util = new Util( $view, $userId ); $session = new Session(); + + $userIds = array(); + + foreach ( $users as $user ) { + + $util = new Util( $view, $user ); + + // Check that the user is encryption capable + if ( $util->ready() ) { + // Construct array of just UIDs for Keymanager{} + $userIds[] = $user; + + } else { + + // Log warning; we can't do necessary setup here + // because we don't have the user passphrase + // TODO: Provide user feedback indicating that + // sharing failed + \OC_Log::write( 'Encryption library', 'File cannot be shared: user "'.$user.'" is not setup for encryption', \OC_Log::WARN ); + + } + + } + - $userPubKeys = Keymanager::getPublicKeys( $view, $users ); + $userPubKeys = Keymanager::getPublicKeys( $view, $userIds ); \OC_FileProxy::$enabled = false; // get the keyfile - $encKeyfile = Keymanager::getFileKey( $view, $userId, $fileTarget ); + $encKeyfile = Keymanager::getFileKey( $view, $owner, $fileTarget ); $privateKey = $session->getPrivateKey(); diff --git a/lib/public/share.php b/lib/public/share.php index 4170783d71e..841240692d8 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -149,62 +149,57 @@ class Share { * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path, $includeOwner = 0 ) { - - $fPath = self::prepFileTarget( $path ); - + public static function getUsersSharingFile( $source, $includeOwner = 0 ) { + //TODO get also the recipients from folders which are shared above the current file // Fetch all shares of this file path from DB $query = \OC_DB::prepare( - 'SELECT - share_type - , share_with - , uid_owner - , permissions + 'SELECT share_with FROM `*PREFIX*share` WHERE - file_target = ?' + item_source = ? AND share_type = ? AND uid_owner = ?' ); - $result = $query->execute( array( $fPath ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_USER, \OCP\User::getUser() ) ); if ( \OC_DB::isError( $result ) ) { - - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $fPath, \OC_Log::ERROR ); - + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); } $shares = array(); while( $row = $result->fetchRow() ) { + $shares[] = $row['share_with']; + } - // Set helpful array keys - $shares[] = array( - 'userId' => $row['share_with'] - , 'owner' => $row['uid_owner'] // we just set this so it can be used once, hugly hack :/ - , 'shareType' => $row['share_type'] - , 'permissions' => $row['permissions'] - ); + // We also need to take group shares into account + + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, \OCP\User::getUser() ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); } + while( $row = $result->fetchRow() ) { + $usersInGroup = \OC_Group::usersInGroup($row['share_with']); + $shares = array_merge($shares, $usersInGroup); + } + if ( ! empty( $shares ) ) { - // Include owner in list of users, if requested if ( $includeOwner == 1 ) { - - // NOTE: The values are incorrect for shareType and - // permissions of the owner; we just include them for - // optional convenience - $shares[] = array( - 'userId' => $shares[0]['owner'] - , 'shareType' => 0 - , 'permissions' => 0 - ); - + $shares[] = \OCP\User::getUser(); } - - return $shares; + + return array_unique($shares); } else { @@ -235,7 +230,7 @@ class Share { public static function getItemSharedWith($itemType, $itemTarget, $format = self::FORMAT_NONE, $parameters = null, $includeCollections = false) { return self::getItems($itemType, $itemTarget, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, $parameters, 1, $includeCollections); } - + /** * @brief Get the item of item type shared with the current user by source * @param string Item type -- cgit v1.2.3 From d1bbb30385260d77b01bc5998465ebe68ccd83d7 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Tue, 12 Feb 2013 16:48:04 +0100 Subject: also find users with access to the file if a folder above the actual file was already shared --- apps/files_encryption/hooks/hooks.php | 30 ++++------- apps/files_encryption/lib/crypt.php | 2 - apps/files_encryption/lib/util.php | 14 +++++ lib/public/share.php | 97 ++++++++++++++++++----------------- 4 files changed, 75 insertions(+), 68 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ebc345a47e7..ffd3e4544f1 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -164,21 +164,7 @@ class Hooks { } /** - * @brief get path of a file. - * @param $fileId id of the file - * @return path of the file - */ - private static function getFilePath($fileId) { - $query = \OC_DB::prepare('SELECT `path`' - .' FROM `*PREFIX*filecache`' - .' WHERE `fileid` = ?'); - $result = $query->execute(array($fileId)); - $row = $result->fetchRow(); - return $row['path']; - } - - /** - * @brief + * @brief get all users with access to the file and encrypt the file key to each of them */ public static function postShared( $params ) { @@ -194,9 +180,11 @@ class Hooks { $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); - $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); + $path = Util::getFilePath($params['itemSource']); + + $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); - return Crypt::encKeyfileToMultipleUsers($shares, self::getFilePath($params['itemSource'])); + return Crypt::encKeyfileToMultipleUsers($shares, $path); } @@ -204,18 +192,20 @@ class Hooks { * @brief */ public static function preUnshare( $params ) { - $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); + + $path = Util::getFilePath($params['itemSource']); + $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); // remove the user from the list from which the file will be unshared unset($shares[$params['shareWith']]); - return Crypt::encKeyfileToMultipleUsers($shares, self::getFilePath($params['itemSource'])); + return Crypt::encKeyfileToMultipleUsers($shares, $path ); } /** * @brief */ public static function preUnshareAll( $params ) { - return Crypt::encKeyfileToMultipleUsers(array(\OCP\User::getUser()), self::getFilePath($params['itemSource'])); + return Crypt::encKeyfileToMultipleUsers(array(\OCP\User::getUser()), Util::getFilePath($params['itemSource'])); } } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index cbdae323e56..ba9f0cb9a2a 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -450,9 +450,7 @@ class Crypt { * @returns encrypted file */ public static function keyEncrypt( $plainContent, $publicKey ) { - openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey ); - return $encryptedContent; } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 52bc74db27a..843727d7ab4 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -472,5 +472,19 @@ class Util { } } + + /** + * @brief get path of a file. + * @param $fileId id of the file + * @return path of the file + */ + public static function getFilePath($fileId) { + $query = \OC_DB::prepare('SELECT `path`' + .' FROM `*PREFIX*filecache`' + .' WHERE `fileid` = ?'); + $result = $query->execute(array($fileId)); + $row = $result->fetchRow(); + return substr($row['path'], 5); + } } diff --git a/lib/public/share.php b/lib/public/share.php index 841240692d8..55ff4d4738f 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -149,64 +149,69 @@ class Share { * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $source, $includeOwner = 0 ) { - //TODO get also the recipients from folders which are shared above the current file - // Fetch all shares of this file path from DB - $query = \OC_DB::prepare( - 'SELECT share_with - FROM - `*PREFIX*share` - WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' - ); - - $result = $query->execute( array( $source, self::SHARE_TYPE_USER, \OCP\User::getUser() ) ); - - if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); - } - + public static function getUsersSharingFile( $path, $includeOwner = 0 ) { + + $user = \OCP\User::getUser(); + $path_parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR)); + $path = ''; $shares = array(); - while( $row = $result->fetchRow() ) { - $shares[] = $row['share_with']; - } - - // We also need to take group shares into account - - $query = \OC_DB::prepare( - 'SELECT share_with - FROM - `*PREFIX*share` - WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' - ); + foreach ($path_parts as $p) { + $path .= '/'.$p; + $meta = \OC\Files\Filesystem::getFileInfo(\OC_Filesystem::normalizePath($path)); + $source = $meta['fileid']; - $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, \OCP\User::getUser() ) ); - - if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); - } - - while( $row = $result->fetchRow() ) { - $usersInGroup = \OC_Group::usersInGroup($row['share_with']); - $shares = array_merge($shares, $usersInGroup); + // Fetch all shares of this file path from DB + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + + $result = $query->execute( array( $source, self::SHARE_TYPE_USER, $user ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + } + + while( $row = $result->fetchRow() ) { + $shares[] = $row['share_with']; + } + + // We also need to take group shares into account + + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + + $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, $user ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + } + + while( $row = $result->fetchRow() ) { + $usersInGroup = \OC_Group::usersInGroup($row['share_with']); + $shares = array_merge($shares, $usersInGroup); + } } - + if ( ! empty( $shares ) ) { // Include owner in list of users, if requested if ( $includeOwner == 1 ) { - $shares[] = \OCP\User::getUser(); + $shares[] = $user; } - return array_unique($shares); - } else { - return false; - } - + } /** -- cgit v1.2.3 From a692264fa416fec44d774bd955a06a65c7c0d158 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Tue, 12 Feb 2013 17:00:33 +0100 Subject: add option to keep duplicates in the list of users with access to a file, e.g. for the unshare operation we need to know if access was granted more than once, for example as group share and as individual share --- apps/files_encryption/hooks/hooks.php | 6 +++--- apps/files_encryption/lib/proxy.php | 11 ++--------- lib/public/share.php | 17 +++++++++++------ 3 files changed, 16 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ffd3e4544f1..5e06948aa50 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -182,7 +182,7 @@ class Hooks { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); return Crypt::encKeyfileToMultipleUsers($shares, $path); @@ -194,11 +194,11 @@ class Hooks { public static function preUnshare( $params ) { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); + $shares = \OCP\Share::getUsersSharingFile( $path, true, false ); // remove the user from the list from which the file will be unshared unset($shares[$params['shareWith']]); - return Crypt::encKeyfileToMultipleUsers($shares, $path ); + return Crypt::encKeyfileToMultipleUsers(array_unique($shares), $path ); } /** diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 40ac411539b..3e4178e8a87 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -118,15 +118,8 @@ class Proxy extends \OC_FileProxy { // $fileOwner = \OC\Files\Filesystem::getOwner( $path ); // List everyone sharing the file - $shares = \OCP\Share::getUsersSharingFile( $filePath, 1 ); - - $userIds = array(); - - foreach ( $shares as $share ) { - - $userIds[] = $share['userId']; - - } + //TODO check, is this path always the path to the source file? + $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ); $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); diff --git a/lib/public/share.php b/lib/public/share.php index 55ff4d4738f..68f5e93baa7 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -145,11 +145,14 @@ class Share { /** * @brief Find which users can access a shared item - * @return bool / array + * @param $path to the file + * @param include owner to the list of users with access to the file + * @param remove duplicates in the result + * @return array * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path, $includeOwner = 0 ) { + public static function getUsersSharingFile( $path, $includeOwner = false, $removeDuplicates = true ) { $user = \OCP\User::getUser(); $path_parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR)); @@ -204,14 +207,16 @@ class Share { if ( ! empty( $shares ) ) { // Include owner in list of users, if requested - if ( $includeOwner == 1 ) { + if ( $includeOwner ) { $shares[] = $user; } + } + + if ( $removeDuplicates ) return array_unique($shares); - } else { - return false; + else { + return $shares; } - } /** -- cgit v1.2.3 From 4952dfe95657ba52f1b39f958100659539831ba8 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Wed, 13 Feb 2013 14:56:39 +0100 Subject: add post_unshare hook, also add public link shares to the list of user with access to a file --- apps/files_encryption/appinfo/app.php | 2 +- apps/files_encryption/hooks/hooks.php | 9 ++++----- apps/files_encryption/lib/crypt.php | 4 +++- lib/public/share.php | 35 ++++++++++++++++++++++++++++------- 4 files changed, 36 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index f83109a18ea..932e8855d07 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -16,7 +16,7 @@ OCP\Util::connectHook( 'OC_User', 'pre_setPassword','OCA\Encryption\Hooks', 'set // 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', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' ); OCP\Util::connectHook( 'OCP\Share', 'pre_unshareAll', 'OCA\Encryption\Hooks', 'preUnshareAll' ); // Webdav-related hooks diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 5e06948aa50..ae05ba78012 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -176,6 +176,8 @@ class Hooks { //TODO: We don't deal with shared folder yet, need to recursively update every file in the folder + if ($params['shareType'] == \OCP\Share::SHARE_TYPE_LINK) + $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); @@ -191,12 +193,9 @@ class Hooks { /** * @brief */ - public static function preUnshare( $params ) { - + public static function postUnshare( $params ) { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, true, false ); - // remove the user from the list from which the file will be unshared - unset($shares[$params['shareWith']]); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); return Crypt::encKeyfileToMultipleUsers(array_unique($shares), $path ); } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index ba9f0cb9a2a..0f465d7d95a 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -450,7 +450,9 @@ class Crypt { * @returns encrypted file */ public static function keyEncrypt( $plainContent, $publicKey ) { - openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey ); + + if (openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey )) error_log("feinifeine"); else error_log("ups"); + return $encryptedContent; } diff --git a/lib/public/share.php b/lib/public/share.php index 68f5e93baa7..f691ae9b39f 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -147,7 +147,6 @@ class Share { * @brief Find which users can access a shared item * @param $path to the file * @param include owner to the list of users with access to the file - * @param remove duplicates in the result * @return array * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' @@ -203,6 +202,25 @@ class Share { $usersInGroup = \OC_Group::usersInGroup($row['share_with']); $shares = array_merge($shares, $usersInGroup); } + + //check for public link shares + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + + $result = $query->execute( array( $source, self::SHARE_TYPE_LINK, $user ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + } + + if ($result->fetchRow()) { + $shares[] = self::SHARE_TYPE_LINK; + } } if ( ! empty( $shares ) ) { @@ -212,11 +230,8 @@ class Share { } } - if ( $removeDuplicates ) - return array_unique($shares); - else { - return $shares; - } + return array_unique($shares); + } /** @@ -475,8 +490,14 @@ class Share { 'itemSource' => $itemSource, 'shareType' => $shareType, 'shareWith' => $shareWith, - )); + )); self::delete($item['id']); + \OC_Hook::emit('OCP\Share', 'post_unshare', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'shareType' => $shareType, + 'shareWith' => $shareWith, + )); return true; } return false; -- cgit v1.2.3 From 9356f9a6bf6e9bd048e31e787d5fcb621de8eebc Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Wed, 13 Feb 2013 17:23:27 +0100 Subject: add post_unshareALll hook, update recursively all keyfiles if a folder was shared/unshared --- apps/files_encryption/appinfo/app.php | 2 +- apps/files_encryption/hooks/hooks.php | 15 ++++++--------- apps/files_encryption/lib/crypt.php | 36 ++++++++++++++++++++++++++++++++++- lib/public/share.php | 5 +++++ 4 files changed, 47 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 932e8855d07..6778e1faa3c 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -17,7 +17,7 @@ OCP\Util::connectHook( 'OC_User', 'pre_setPassword','OCA\Encryption\Hooks', 'set // Sharing-related hooks OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' ); -OCP\Util::connectHook( 'OCP\Share', 'pre_unshareAll', 'OCA\Encryption\Hooks', 'preUnshareAll' ); +OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' ); // Webdav-related hooks OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ae05ba78012..34ed11c7e24 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -176,17 +176,13 @@ class Hooks { //TODO: We don't deal with shared folder yet, need to recursively update every file in the folder - if ($params['shareType'] == \OCP\Share::SHARE_TYPE_LINK) - $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, true ); - - return Crypt::encKeyfileToMultipleUsers($shares, $path); + return Crypt::updateKeyfile($path); } @@ -195,16 +191,17 @@ class Hooks { */ public static function postUnshare( $params ) { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, true ); - return Crypt::encKeyfileToMultipleUsers(array_unique($shares), $path ); + return Crypt::updateKeyfile($path); } /** * @brief */ - public static function preUnshareAll( $params ) { - return Crypt::encKeyfileToMultipleUsers(array(\OCP\User::getUser()), Util::getFilePath($params['itemSource'])); + public static function postUnshareAll( $params ) { + $path = Util::getFilePath($params['itemSource']); + + return Crypt::updateKeyfile($path); } } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 0f465d7d95a..18e9535bf35 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -750,7 +750,7 @@ class Crypt { * @param $users list of users which should be able to access the file * @param $fileTarget target of the file */ - public static function encKeyfileToMultipleUsers($users, $filePath) { + private static function encKeyfileToMultipleUsers($users, $filePath) { $view = new \OC_FilesystemView( '/' ); $owner = \OCP\User::getUser(); $util = new Util( $view, $userId ); @@ -810,4 +810,38 @@ class Crypt { return true; } + + /** + * @brief update keyfile encryption for given path and all sub folders/files + * @param path which needs to be updated + * @return bool success + */ + public static function updateKeyfile($path) { + + $filesView = \OCP\Files::getStorage('files'); + + $result = true; + + if ( $filesView->is_dir($path) ) { + $content = $filesView->getDirectoryContent($path); + foreach ( $content as $c) { + $path = substr($c['path'], 5); + if ( $filesView->is_dir($path) ) { + error_log("dive into $path"); + $result &= self::updateKeyfile($path); + } else { + error_log("encKeyFileToMultipleUsers $path"); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); + $result &= self::encKeyfileToMultipleUsers($shares, $path); + } + } + } else { + error_log("encKeyFileToMultipleUsers single file: " . $path); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); + $result = self::encKeyfileToMultipleUsers($shares, $path); + } + + return $result; + + } } \ No newline at end of file diff --git a/lib/public/share.php b/lib/public/share.php index f691ae9b39f..d1297c6e59e 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -520,6 +520,11 @@ class Share { foreach ($shares as $share) { self::delete($share['id']); } + \OC_Hook::emit('OCP\Share', 'post_unshareAll', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'shares' => $shares + )); return true; } return false; -- cgit v1.2.3 From 5005195db005fd0d7c8fdf1a73e12c4a4619acb9 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Wed, 13 Feb 2013 17:57:45 +0100 Subject: create keypair for ownCloud with empty passphrase, will be used for public link shares --- apps/files_encryption/lib/crypt.php | 5 +---- apps/files_encryption/lib/session.php | 28 ++++++++++++++++++++++++++++ lib/public/share.php | 2 +- 3 files changed, 30 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 18e9535bf35..2e5912a8683 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -763,7 +763,7 @@ class Crypt { $util = new Util( $view, $user ); // Check that the user is encryption capable - if ( $util->ready() ) { + if ( $util->ready() && $user == 'ownCloud' ) { // Construct array of just UIDs for Keymanager{} $userIds[] = $user; @@ -827,16 +827,13 @@ class Crypt { foreach ( $content as $c) { $path = substr($c['path'], 5); if ( $filesView->is_dir($path) ) { - error_log("dive into $path"); $result &= self::updateKeyfile($path); } else { - error_log("encKeyFileToMultipleUsers $path"); $shares = \OCP\Share::getUsersSharingFile( $path, true ); $result &= self::encKeyfileToMultipleUsers($shares, $path); } } } else { - error_log("encKeyFileToMultipleUsers single file: " . $path); $shares = \OCP\Share::getUsersSharingFile( $path, true ); $result = self::encKeyfileToMultipleUsers($shares, $path); } diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 769a40b359f..ebf7edcd715 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -27,6 +27,34 @@ namespace OCA\Encryption; */ class Session { + + /** + * @brief if session is started, check if ownCloud key pair is set up, if not create it + * + * The ownCloud key pair is used to allow public link sharing even if encryption is enabled + */ + public function __construct() { + $view = new \OC\Files\View('/'); + if (!$view->is_dir('owncloud_private_key')) { + $view->mkdir('owncloud_private_key'); + } + + if (!$view->file_exists("/public-keys/owncloud.public.key") || !$view->file_exists("/owncloud_private_key/owncloud.private.key") ) { + + $keypair = Crypt::createKeypair(); + + \OC_FileProxy::$enabled = false; + // Save public key + $view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] ); + // Encrypt private key empthy passphrase + $encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' ); + // Save private key + error_log("encrypted private key: " . $encryptedPrivateKey ); + $view->file_put_contents( '/owncloud_private_key/owncloud.private.key', $encryptedPrivateKey ); + + \OC_FileProxy::$enabled = true; + } + } /** * @brief Sets user private key to session diff --git a/lib/public/share.php b/lib/public/share.php index d1297c6e59e..720337c3c38 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -219,7 +219,7 @@ class Share { } if ($result->fetchRow()) { - $shares[] = self::SHARE_TYPE_LINK; + $shares[] = "ownCloud"; } } -- cgit v1.2.3 From 40efeb91878e72eb5c2eb1ab50574cda9435e0fa Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Fri, 22 Feb 2013 16:02:27 +0100 Subject: isSharedFile() doesn't detect all shares, just use getUsersSharingFile() directly either you get a list of users or not --- apps/files_encryption/lib/proxy.php | 6 +----- lib/public/share.php | 34 ---------------------------------- 2 files changed, 1 insertion(+), 39 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 9e6a11d9d48..ebe09dc075a 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -113,14 +113,10 @@ class Proxy extends \OC_FileProxy { $encData = Crypt::symmetricEncryptFileContentKeyfile( $data ); // Check if the keyfile needs to be shared - if ( \OCP\Share::isSharedFile( $filePath ) ) { + if ( ($userIds = \OCP\Share::getUsersSharingFile( $filePath, true )) ) { // $fileOwner = \OC\Files\Filesystem::getOwner( $path ); - // List everyone sharing the file - //TODO check, is this path always the path to the source file? - $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ); - $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); \OC_FileProxy::$enabled = false; diff --git a/lib/public/share.php b/lib/public/share.php index 720337c3c38..7630c8ae6cb 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -108,41 +108,7 @@ class Share { return $path; } - - public static function isSharedFile( $path ) { - - $fPath = self::prepFileTarget( $path ); - - // Fetch all shares of this file path from DB - $query = \OC_DB::prepare( - 'SELECT - id - FROM - `*PREFIX*share` - WHERE - file_target = ?' - ); - - $result = $query->execute( array( $fPath ) ); - - if ( \OC_DB::isError( $result ) ) { - - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage( $result ) . ', path=' . $fPath, \OC_Log::ERROR ); - - } - - if ( $result->fetchRow() !== false ) { - return true; - - } else { - - return false; - - } - - } - /** * @brief Find which users can access a shared item * @param $path to the file -- cgit v1.2.3 From fe58e4b1a6a0f3b63afe74690986493facdad2c4 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Thu, 18 Apr 2013 17:46:04 +0200 Subject: we need to add the owner of the file as parameter in case someone else like the owner edits the file; if $includeOwner is set than add owner also if no other recipient was found. This changes enable all user with write access to the file to edit it and to encrypt it to the right list of users again --- lib/public/share.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/public/share.php b/lib/public/share.php index 876de892572..acdf895c920 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -127,21 +127,21 @@ class Share { /** * @brief Find which users can access a shared item * @param $path to the file + * @param $user owner of the file * @param include owner to the list of users with access to the file * @return array * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path, $includeOwner = false, $removeDuplicates = true ) { + public static function getUsersSharingFile( $path, $user, $includeOwner = false, $removeDuplicates = true ) { - $user = \OCP\User::getUser(); $path_parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR)); $path = ''; $shares = array(); - + $view = new \OC\Files\View('/'.$user.'/files/'); foreach ($path_parts as $p) { $path .= '/'.$p; - $meta = \OC\Files\Filesystem::getFileInfo(\OC_Filesystem::normalizePath($path)); + $meta = $view->getFileInfo(\OC_Filesystem::normalizePath($path)); $source = $meta['fileid']; // Fetch all shares of this file path from DB @@ -203,12 +203,9 @@ class Share { $shares[] = "ownCloud"; } } - - if ( ! empty( $shares ) ) { - // Include owner in list of users, if requested - if ( $includeOwner ) { - $shares[] = $user; - } + // Include owner in list of users, if requested + if ( $includeOwner ) { + $shares[] = $user; } return array_unique($shares); -- cgit v1.2.3 From b24a673714289bf515c93999a1dd0dfc552eb7cc Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Mon, 22 Apr 2013 14:12:18 +0200 Subject: the owner uid is not interesting. We want to get all users who have access to the given item source, no matter from whom it was shared --- lib/public/share.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/public/share.php b/lib/public/share.php index acdf895c920..9fd8eb42fb7 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -150,10 +150,10 @@ class Share { FROM `*PREFIX*share` WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' + item_source = ? AND share_type = ?' ); - $result = $query->execute( array( $source, self::SHARE_TYPE_USER, $user ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_USER ) ); if ( \OC_DB::isError( $result ) ) { \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); @@ -170,10 +170,10 @@ class Share { FROM `*PREFIX*share` WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' + item_source = ? AND share_type = ?' ); - $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, $user ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP ) ); if ( \OC_DB::isError( $result ) ) { \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); @@ -190,10 +190,10 @@ class Share { FROM `*PREFIX*share` WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' + item_source = ? AND share_type = ?' ); - $result = $query->execute( array( $source, self::SHARE_TYPE_LINK, $user ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_LINK ) ); if ( \OC_DB::isError( $result ) ) { \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); -- cgit v1.2.3 From b5cb5dab513441b8c914aaa043921d0affae4604 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Mon, 22 Apr 2013 14:30:10 +0200 Subject: fix encryption to owncloud user for public link shares --- apps/files_encryption/lib/keymanager.php | 2 +- apps/files_encryption/lib/util.php | 2 +- lib/public/share.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index f23423062b9..6fb1f128b5e 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -54,7 +54,7 @@ class Keymanager { \OC_FileProxy::$enabled = false; - return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); + return $view->file_get_contents( '/public-keys/' . $userId . '.public.key' ); \OC_FileProxy::$enabled = true; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 1ba339c15df..143ba69f254 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -668,7 +668,7 @@ class Util { // public system user 'ownCloud' (for public shares) if ( $util->ready() - or $user == 'ownCloud' + or $user == 'owncloud' ) { // Construct array of ready UIDs for Keymanager{} diff --git a/lib/public/share.php b/lib/public/share.php index 9fd8eb42fb7..5cd556c6acb 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -200,7 +200,7 @@ class Share { } if ($result->fetchRow()) { - $shares[] = "ownCloud"; + $shares[] = "owncloud"; } } // Include owner in list of users, if requested -- cgit v1.2.3 From 25ff32db6bec0992b0fac18b04345aa5e99f4ea1 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 23 Apr 2013 22:20:31 +0200 Subject: Added post proxy for getFileInfo. This is needed for WebDAV and FileSize @samtuke and @schiesbn you guys know a better solution? --- lib/files/view.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/files/view.php b/lib/files/view.php index f607bb59aac..bd4812f8f81 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -724,6 +724,9 @@ class View { $data['permissions'] = $permissions; } } + + $data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data); + return $data; } -- cgit v1.2.3 From fac288a4ad8f6db907c0a2ddfeb0b772fe616db5 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 15:20:06 +0200 Subject: added unencrypted file size to file cache improved file size calculation and speeds --- apps/files_encryption/lib/proxy.php | 113 +++++++++++++---------------------- apps/files_encryption/lib/stream.php | 14 +++-- db_structure.xml | 8 +++ lib/files/cache/cache.php | 11 ++-- 4 files changed, 62 insertions(+), 84 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index b805ec648d4..c07b9a8a7aa 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -108,7 +108,8 @@ class Proxy extends \OC_FileProxy { $size = strlen( $data ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; // Check if there is an existing key we can reuse if ( $encKeyfile = Keymanager::getFileKey( $rootView, $userId, $filePath ) ) { @@ -135,10 +136,8 @@ class Proxy extends \OC_FileProxy { // Fetch public keys for all users who will share the file $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); - - \OC_FileProxy::$enabled = false; - - // Encrypt plain keyfile to multiple sharefiles + + // Encrypt plain keyfile to multiple sharefiles $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); // Save sharekeys to user folders @@ -157,7 +156,7 @@ class Proxy extends \OC_FileProxy { \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); // Re-enable proxy - our work is done - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; } } @@ -182,9 +181,10 @@ class Proxy extends \OC_FileProxy { // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - // If data is a catfile + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + // If data is a catfile if ( Crypt::mode() == 'server' && Crypt::isCatfileContent( $data ) // TODO: Do we really need this check? Can't we assume it is properly encrypted? @@ -215,7 +215,7 @@ class Proxy extends \OC_FileProxy { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; if ( ! isset( $plainData ) ) { @@ -240,7 +240,8 @@ class Proxy extends \OC_FileProxy { $path = Keymanager::fixPartialFilePath( $path ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView( '/' ); @@ -265,7 +266,7 @@ class Proxy extends \OC_FileProxy { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; // If we don't return true then file delete will fail; better // to leave orphaned keyfiles than to disallow file deletion @@ -282,6 +283,7 @@ class Proxy extends \OC_FileProxy { { // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); @@ -318,7 +320,7 @@ class Proxy extends \OC_FileProxy { // Rename keyfile so it isn't orphaned $result = $view->rename($oldKeyfilePath, $newKeyfilePath); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -337,9 +339,10 @@ class Proxy extends \OC_FileProxy { $path_f = implode( '/', array_slice( $path_split, 3 ) ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - $meta = stream_get_meta_data( $result ); + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $meta = stream_get_meta_data( $result ); $view = new \OC_FilesystemView( '' ); @@ -369,13 +372,13 @@ class Proxy extends \OC_FileProxy { // NOTE: this is the case for new files saved via WebDAV - if ( - $view->file_exists( $path ) - and $view->filesize( $path ) > 0 - ) { - $x = $view->file_get_contents( $path ); - - $tmp = tmpfile(); +// if ( +// $view->file_exists( $path ) +// and $view->filesize( $path ) > 0 +// ) { +// $x = $view->file_get_contents( $path ); +// +// $tmp = tmpfile(); // // Make a temporary copy of the original file // \OCP\Files::streamCopy( $result, $tmp ); @@ -387,14 +390,14 @@ class Proxy extends \OC_FileProxy { // // fclose( $tmp ); - } +// } $result = fopen( 'crypt://'.$path_f, $meta['mode'] ); } // Re-enable the proxy - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -417,15 +420,15 @@ class Proxy extends \OC_FileProxy { // if path is a folder do nothing if(is_array($data) && array_key_exists('size', $data)) { // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; + // get file size $data['size'] = self::postFileSize($path, $data['size']); // Re-enable the proxy - \OC_FileProxy::$enabled = true; - - trigger_error('postGetFileInfo '.$path.' size: '.$data['size']); + \OC_FileProxy::$enabled = $proxyStatus; } return $data; @@ -437,7 +440,7 @@ class Proxy extends \OC_FileProxy { $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); - $data['size'] = $cached['size']; + $data['size'] = $cached['unencrypted_size']; } @@ -453,56 +456,20 @@ class Proxy extends \OC_FileProxy { return $size; } + $path = Keymanager::fixPartialFilePath( $path ); + // Reformat path for use with OC_FSV $path_split = explode('/', $path); $path_f = implode('/', array_slice($path_split, 3)); - $userId = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - - - // FIXME: is there a better solution to check if file belongs to files path? - // only get file size if file is in 'files' path - if (count($path_split) >= 2 && $path_split[2] == 'files' && $util->isEncryptedPath($path)) { - - // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - // open stream - $result = fopen('crypt://' . $path_f, "r"); - - if(is_resource($result)) { - // don't trust the given size, allways get the size from filesystem - $size = $view->filesize($path); - - // calculate last chunk nr - $lastChunckNr = floor($size / 8192); - - // calculate last chunk position - $lastChunckPos = ($lastChunckNr * 8192); - - // seek to end - fseek($result, $lastChunckPos); - - // get the content of the last chunck - $lastChunkContent = fgets($result); - - // calc the real file size with the size of the last chunk - $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); - - // set the size - $size = $realSize; - } - - // enable proxy - \OC_FileProxy::$enabled = true; - - return $size; + // get file info from database/cache + $fileInfo = \OC\Files\Filesystem::getFileInfo($path_f); + // if file is encrypted return real file size + if(is_array($fileInfo) && $fileInfo['encrypted'] == 1) { + return $fileInfo['unencrypted_size']; } else { - - return $size; - + return $fileInfo['size']; } } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 9a37c3b08ee..7e42627f8ca 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -64,6 +64,7 @@ class Stream { private $count; private $writeCache; public $size; + public $unencryptedSize; private $publicKey; private $keyfile; private $encKeyfile; @@ -105,6 +106,7 @@ class Stream { } else { // 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; if ( @@ -116,6 +118,7 @@ class Stream { // We're writing a new file so start write counter with 0 bytes $this->size = 0; + $this->unencryptedSize = 0; } else { @@ -129,7 +132,7 @@ class Stream { $this->handle = $this->rootView->fopen( $this->rawPath, $mode ); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; if ( ! is_resource( $this->handle ) ) { @@ -301,7 +304,7 @@ class Stream { // 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 - \OC_FileProxy::$enabled = false; + //\OC_FileProxy::$enabled = false; // Get the length of the unencrypted data that we are handling $length = strlen( $data ); @@ -438,7 +441,8 @@ class Stream { } $this->size = max( $this->size, $pointer + $length ); - + $this->unencryptedSize += $length; + return $length; } @@ -501,9 +505,7 @@ class Stream { $this->meta['mode']!='r' and $this->meta['mode']!='rb' ) { - - \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => true, 'size' => $this->size ), '' ); - + \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => 1, 'size' => $this->size, 'unencrypted_size' => $this->unencryptedSize ), '' ); } return fclose( $this->handle ); diff --git a/db_structure.xml b/db_structure.xml index dce90697b1c..366f51a82d0 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -288,6 +288,14 @@ 4 + + unencrypted_size + integer + + true + 8 + + etag text diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 71b70abe3fe..4e32ff2ba8a 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -117,7 +117,7 @@ class Cache { $params = array($file); } $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` ' . $where); $result = $query->execute($params); $data = $result->fetchRow(); @@ -133,6 +133,7 @@ class Cache { $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; $data['encrypted'] = (bool)$data['encrypted']; + $data['unencrypted_size'] = (int)$data['unencrypted_size']; $data['storage'] = $this->storageId; $data['mimetype'] = $this->getMimetype($data['mimetype']); $data['mimepart'] = $this->getMimetype($data['mimepart']); @@ -151,7 +152,7 @@ class Cache { $fileId = $this->getId($folder); if ($fileId > -1) { $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); $result = $query->execute(array($fileId)); $files = $result->fetchAll(); @@ -234,7 +235,7 @@ class Cache { * @return array */ function buildParts(array $data) { - $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag'); + $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'unencrypted_size', 'etag'); $params = array(); $queryParts = array(); foreach ($data as $name => $value) { @@ -391,7 +392,7 @@ class Cache { */ public function search($pattern) { $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' ); $result = $query->execute(array($pattern, $this->numericId)); @@ -417,7 +418,7 @@ class Cache { $where = '`mimepart` = ?'; } $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' ); $mimetype = $this->getMimetypeId($mimetype); -- cgit v1.2.3 From 672d177f10e44581ecc9f37844681afaa06c0272 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 22:43:15 +0200 Subject: added post rename proxy --- lib/files/view.php | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/files/view.php b/lib/files/view.php index bd4812f8f81..d0fc5910e6c 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -362,6 +362,7 @@ class View { list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->rename($internalPath1, $internalPath2); + \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2); } else { $result = false; } -- cgit v1.2.3 From 807740a07a5385b0761aa23128f859a203e8b71a Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Wed, 15 May 2013 10:19:38 +0200 Subject: fix for losing mount point "/" --- lib/files/filesystem.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index eadd8a93faf..d60d430d77c 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -222,7 +222,10 @@ class Filesystem { return false; } self::$defaultInstance = new View($root); - self::$mounts = new Mount\Manager(); + + if(!self::$mounts) { + self::$mounts = new Mount\Manager(); + } //load custom mount config self::initMountPoints($user); -- cgit v1.2.3 From 751487ded7657c2cbc56717105c2891c7c967b42 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Wed, 15 May 2013 10:20:19 +0200 Subject: merge changes for files_encryption --- lib/public/share.php | 82 +++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 40 deletions(-) (limited to 'lib') diff --git a/lib/public/share.php b/lib/public/share.php index 29f9a1f0953..0d90ffb9b7b 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -133,83 +133,83 @@ class Share { * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path, $user, $includeOwner = false, $removeDuplicates = true ) { + public static function getUsersSharingFile($path, $user, $includeOwner = false, $removeDuplicates = true) { $path_parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR)); $path = ''; $shares = array(); - $view = new \OC\Files\View('/'.$user.'/files/'); + $publicShare = false; + $view = new \OC\Files\View('/' . $user . '/files/'); foreach ($path_parts as $p) { - $path .= '/'.$p; + $path .= '/' . $p; $meta = $view->getFileInfo(\OC_Filesystem::normalizePath($path)); $source = $meta['fileid']; - + // Fetch all shares of this file path from DB $query = \OC_DB::prepare( - 'SELECT share_with - FROM - `*PREFIX*share` - WHERE - item_source = ? AND share_type = ?' + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ?' ); - - $result = $query->execute( array( $source, self::SHARE_TYPE_USER ) ); - if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + $result = $query->execute(array($source, self::SHARE_TYPE_USER)); + + if (\OC_DB::isError($result)) { + \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR); } - while( $row = $result->fetchRow() ) { + while ($row = $result->fetchRow()) { $shares[] = $row['share_with']; } // We also need to take group shares into account $query = \OC_DB::prepare( - 'SELECT share_with - FROM - `*PREFIX*share` - WHERE - item_source = ? AND share_type = ?' + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ?' ); - - $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP ) ); - if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + $result = $query->execute(array($source, self::SHARE_TYPE_GROUP)); + + if (\OC_DB::isError($result)) { + \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR); } - while( $row = $result->fetchRow() ) { + while ($row = $result->fetchRow()) { $usersInGroup = \OC_Group::usersInGroup($row['share_with']); $shares = array_merge($shares, $usersInGroup); } - + //check for public link shares $query = \OC_DB::prepare( - 'SELECT share_with - FROM - `*PREFIX*share` - WHERE - item_source = ? AND share_type = ?' + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ?' ); - - $result = $query->execute( array( $source, self::SHARE_TYPE_LINK ) ); - - if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + + $result = $query->execute(array($source, self::SHARE_TYPE_LINK)); + + if (\OC_DB::isError($result)) { + \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR); } - + if ($result->fetchRow()) { - $shares[] = "owncloud"; + $publicShare = true; } } // Include owner in list of users, if requested - if ( $includeOwner ) { + if ($includeOwner) { $shares[] = $user; } - - return array_unique($shares); + return array("users" => array_unique($shares), "public" => $publicShare); } /** @@ -514,6 +514,7 @@ class Share { 'fileSource' => $item['file_source'], 'shareType' => $shareType, 'shareWith' => $shareWith, + 'itemParent' => $item['parent'], )); self::delete($item['id']); \OC_Hook::emit('OCP\Share', 'post_unshare', array( @@ -521,6 +522,7 @@ class Share { 'itemSource' => $itemSource, 'shareType' => $shareType, 'shareWith' => $shareWith, + 'itemParent' => $item['parent'], )); return true; } -- cgit v1.2.3 From 0916769f6764e2497f820419121599c3ce121e87 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Wed, 15 May 2013 17:00:01 +0200 Subject: fix for SQLite3Result::fetchArray(): The SQLite3Result object has not been correctly initialised in post_addToGroup --- lib/public/share.php | 53 +++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/public/share.php b/lib/public/share.php index 0d90ffb9b7b..b2eeb29234a 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1519,31 +1519,34 @@ class Share { } public static function post_addToGroup($arguments) { - // Find the group shares and check if the user needs a unique target - $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'); - $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'])); - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,' - .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,' - .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); - while ($item = $result->fetchRow()) { - if ($item['item_type'] == 'file' || $item['item_type'] == 'file') { - $itemTarget = null; - } else { - $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, - $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); - } - if (isset($item['file_source'])) { - $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, - $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); - } else { - $fileTarget = null; - } - // Insert an extra row for the group share if the item or file target is unique for this user - if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) { - $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], - self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], - $item['stime'], $item['file_source'], $fileTarget)); - \OC_DB::insertid('*PREFIX*share'); + + if(\OC_Config::getValue('installed')) { + // Find the group shares and check if the user needs a unique target + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'); + $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'])); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,' + .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,' + .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + while ($item = $result->fetchRow()) { + if ($item['item_type'] == 'file' || $item['item_type'] == 'file') { + $itemTarget = null; + } else { + $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); + } + if (isset($item['file_source'])) { + $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); + } else { + $fileTarget = null; + } + // Insert an extra row for the group share if the item or file target is unique for this user + if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) { + $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], + self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], + $item['stime'], $item['file_source'], $fileTarget)); + \OC_DB::insertid('*PREFIX*share'); + } } } } -- cgit v1.2.3 From 9d1e60325c6f478484ff8f70ff3cd13d9d7d4913 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Thu, 16 May 2013 14:53:04 +0200 Subject: allow admin to recover users files in case of password lost --- apps/files_encryption/hooks/hooks.php | 73 +++++++++++++++++++------- apps/files_encryption/js/settings-admin.js | 2 +- apps/files_encryption/lib/helper.php | 2 +- apps/files_encryption/lib/util.php | 84 +++++++++++++++++++++++++++++- lib/user.php | 7 +-- settings/ajax/changepassword.php | 5 +- settings/css/settings.css | 2 + settings/js/users.js | 4 +- settings/templates/personal.php | 2 +- settings/templates/users.php | 5 ++ settings/users.php | 3 ++ 11 files changed, 159 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index f843c7027d5..0af0845d7c1 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -142,32 +142,67 @@ class Hooks { * @brief Change a user's encryption passphrase * @param array $params keys: uid, password */ - public static function setPassphrase( $params ) { - + public static function setPassphrase($params) { + // Only attempt to change passphrase if server-side encryption // is in use (client-side encryption does not have access to // the necessary keys) - if ( Crypt::mode() == 'server' ) { + if (Crypt::mode() == 'server') { - $view = new \OC_FilesystemView( '/' ); + if ($params['uid'] == \OCP\User::getUser()) { - $session = new Session($view); - - // Get existing decrypted private key - $privateKey = $session->getPrivateKey(); - - // Encrypt private key with new user pwd as passphrase - $encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $privateKey, $params['password'] ); - - // Save private key - Keymanager::setPrivateKey( $encryptedPrivateKey ); - - // NOTE: Session does not need to be updated as the - // private key has not changed, only the passphrase - // used to decrypt it has changed + $view = new \OC_FilesystemView('/'); + + $session = new Session($view); + + // Get existing decrypted private key + $privateKey = $session->getPrivateKey(); + + // Encrypt private key with new user pwd as passphrase + $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($privateKey, $params['password']); + + // Save private key + Keymanager::setPrivateKey($encryptedPrivateKey); + + // NOTE: Session does not need to be updated as the + // private key has not changed, only the passphrase + // used to decrypt it has changed + + } else { // admin changed the password for a different user, create new keys and reencrypt file keys + + $user = $params['uid']; + $recoveryPassword = $params['recoveryPassword']; + $newUserPassword = $params['password']; + + $view = new \OC_FilesystemView('/'); + + // make sure that the users home is mounted + \OC\Files\Filesystem::initMountPoints($user); + + $keypair = Crypt::createKeypair(); + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + // Save public key + $view->file_put_contents( '/public-keys/'.$user.'.public.key', $keypair['publicKey'] ); + + // Encrypt private key empthy passphrase + $encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], $newUserPassword ); + + // Save private key + $view->file_put_contents( '/'.$user.'/files_encryption/'.$user.'.private.key', $encryptedPrivateKey ); + + if ( $recoveryPassword ) { // if recovery key is set we can re-encrypt the key files + $util = new Util($view, $user); + $util->recoverUsersFiles($recoveryPassword); + } + + \OC_FileProxy::$enabled = $proxyStatus; + } } - } /* diff --git a/apps/files_encryption/js/settings-admin.js b/apps/files_encryption/js/settings-admin.js index 9bc6ab6433c..dbae42b011c 100644 --- a/apps/files_encryption/js/settings-admin.js +++ b/apps/files_encryption/js/settings-admin.js @@ -69,7 +69,7 @@ $(document).ready(function(){ } ); - // change password + // change recovery password $('input:password[name="changeRecoveryPassword"]').keyup(function(event) { var oldRecoveryPassword = $('input:password[id="oldRecoveryPassword"]').val(); diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 6d5aae4e8b5..86d860465e6 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -46,7 +46,7 @@ class Helper { public static function registerUserHooks() { \OCP\Util::connectHook( 'OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login' ); - \OCP\Util::connectHook( 'OC_User', 'pre_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase' ); + \OCP\Util::connectHook( 'OC_User', 'post_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase' ); \OCP\Util::connectHook( 'OC_User', 'post_createUser', 'OCA\Encryption\Hooks', 'postCreateUser' ); \OCP\Util::connectHook( 'OC_User', 'post_deleteUser', 'OCA\Encryption\Hooks', 'postDeleteUser' ); } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 91d86cc8558..fab807b0141 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -929,7 +929,7 @@ class Util { // Get the current users's private key for decrypting existing keyfile $privateKey = $session->getPrivateKey(); - + $fileOwner = \OC\Files\Filesystem::getOwner( $filePath ); // Decrypt keyfile @@ -1336,7 +1336,7 @@ class Util { } } - /** + /** * @brief remove recovery key to all encrypted files */ public function removeRecoveryKeys($path = '/') { @@ -1351,4 +1351,84 @@ class Util { } } } + + /** + * @brief decrypt given file with recovery key and encrypt it again to the owner and his new key + * @param type $file + * @param type $privateKey recovery key to decrypt the file + */ + private function recoverFile($file, $privateKey) { + + $sharingEnabled = \OCP\Share::isEnabled(); + + // Find out who, if anyone, is sharing the file + if ($sharingEnabled) { + $result = \OCP\Share::getUsersSharingFile($file, $this->userId, true, true, true); + $userIds = $result['users']; + $userIds[] = $this->recoveryKeyId; + if ($result['public']) { + $userIds[] = $this->publicShareKeyId; + } + } else { + $userIds = array($this->userId, $this->recoveryKeyId); + } + $filteredUids = $this->filterShareReadyUsers($userIds); + + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + //decrypt file key + $encKeyfile = $this->view->file_get_contents($this->keyfilesPath.$file.".key"); + $shareKey = $this->view->file_get_contents($this->shareKeysPath.$file.".".$this->recoveryKeyId.".shareKey"); + $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); + // encrypt file key again to all users, this time with the new public key for the recovered use + $userPubKeys = Keymanager::getPublicKeys($this->view, $filteredUids['ready']); + $multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys); + + // write new keys to filesystem TDOO! + $this->view->file_put_contents($this->keyfilesPath.$file.'.key', $multiEncKey['data']); + foreach ($multiEncKey['keys'] as $userId => $shareKey) { + $shareKeyPath = $this->shareKeysPath.$file.'.'.$userId.'.shareKey'; + $this->view->file_put_contents($shareKeyPath, $shareKey); + } + + // Return proxy to original status + \OC_FileProxy::$enabled = $proxyStatus; + } + + /** + * @brief collect all files and recover them one by one + * @param type $path to look for files keys + * @param type $privateKey private recovery key which is used to decrypt the files + */ + private function recoverAllFiles($path, $privateKey) { + $dirContent = $this->view->getDirectoryContent($this->keyfilesPath . $path); + foreach ($dirContent as $item) { + $filePath = substr($item['path'], 25); + if ($item['type'] == 'dir') { + $this->addRecoveryKey($filePath . '/', $privateKey); + } else { + $file = substr($filePath, 0, -4); + $this->recoverFile($file, $privateKey); + } + } + } + + /** + * @brief recover users files in case of password lost + * @param type $recoveryPassword + */ + public function recoverUsersFiles($recoveryPassword) { + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $encryptedKey = $this->view->file_get_contents( '/owncloud_private_key/'.$this->recoveryKeyId.'.private.key' ); + $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $recoveryPassword ); + + \OC_FileProxy::$enabled = $proxyStatus; + + $this->recoverAllFiles('/', $privateKey); + } } diff --git a/lib/user.php b/lib/user.php index 226b716188d..833e8866592 100644 --- a/lib/user.php +++ b/lib/user.php @@ -393,13 +393,14 @@ class OC_User { * @brief Set password * @param $uid The username * @param $password The new password + * @param $recoveryPassword for the encryption app to reset encryption keys * @returns true/false * * Change the password of a user */ - public static function setPassword( $uid, $password ) { + public static function setPassword( $uid, $password, $recoveryPassword = null ) { $run = true; - OC_Hook::emit( "OC_User", "pre_setPassword", array( "run" => &$run, "uid" => $uid, "password" => $password )); + OC_Hook::emit( "OC_User", "pre_setPassword", array( "run" => &$run, "uid" => $uid, "password" => $password, "recoveryPassword" => $recoveryPassword )); if( $run ) { $success = false; @@ -412,7 +413,7 @@ class OC_User { } // invalidate all login cookies OC_Preferences::deleteApp($uid, 'login_token'); - OC_Hook::emit( "OC_User", "post_setPassword", array( "uid" => $uid, "password" => $password )); + OC_Hook::emit( "OC_User", "post_setPassword", array( "uid" => $uid, "password" => $password, "recoveryPassword" => $recoveryPassword )); return $success; } else{ diff --git a/settings/ajax/changepassword.php b/settings/ajax/changepassword.php index 4f16bff63d5..fe63f27a6e2 100644 --- a/settings/ajax/changepassword.php +++ b/settings/ajax/changepassword.php @@ -8,8 +8,9 @@ OC_JSON::checkLoggedIn(); OC_APP::loadApps(); $username = isset($_POST["username"]) ? $_POST["username"] : OC_User::getUser(); -$password = isset($_POST["newpassword"]) ? $_POST["newpassword"] : null; +$password = isset($_POST["password"]) ? $_POST["password"] : null; $oldPassword=isset($_POST["oldpassword"])?$_POST["oldpassword"]:''; +$recoveryPassword=isset($_POST["recoveryPassword"])?$_POST["recoveryPassword"]:null; $userstatus = null; if(OC_User::isAdminUser(OC_User::getUser())) { @@ -28,7 +29,7 @@ if(is_null($userstatus)) { } // Return Success story -if(!is_null($password) && OC_User::setPassword( $username, $password )) { +if(!is_null($password) && OC_User::setPassword( $username, $password, $recoveryPassword )) { OC_JSON::success(array("data" => array( "username" => $username ))); } else{ diff --git a/settings/css/settings.css b/settings/css/settings.css index 46a0bbe7c32..950e8929012 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -45,6 +45,8 @@ table:not(.nostyle) { width:100%; } #rightcontent { padding-left: 1em; } div.quota { float:right; display:block; position:absolute; right:25em; top:-1px; } div.quota-select-wrapper { position: relative; } +div.recoveryPassword { left:50em; display:block; position:absolute; top:-1px; } +input#recoveryPassword {width:15em;} select.quota { position:absolute; left:0; top:0; width:10em; } select.quota-user { position:relative; left:0; top:0; width:10em; } div.quota>span { position:absolute; right:0; white-space:nowrap; top:.7em; color:#888; text-shadow:0 1px 0 #fff; } diff --git a/settings/js/users.js b/settings/js/users.js index 690c9ad0464..9bd7f31f0b2 100644 --- a/settings/js/users.js +++ b/settings/js/users.js @@ -351,9 +351,11 @@ $(document).ready(function () { input.keypress(function (event) { if (event.keyCode == 13) { if ($(this).val().length > 0) { + var recoveryPasswordVal = $('input:password[id="recoveryPassword"]').val(); + console.log("RECOVERY PASSWD: " + recoveryPasswordVal); $.post( OC.filePath('settings', 'ajax', 'changepassword.php'), - {username: uid, password: $(this).val()}, + {username: uid, password: $(this).val(), recoveryPassword: recoveryPasswordVal}, function (result) { } ); diff --git a/settings/templates/personal.php b/settings/templates/personal.php index cfb45e99c4d..da812e8ed9a 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -38,7 +38,7 @@ if($_['passwordChangeSupported']) {
t('Your password was changed');?>
t('Unable to change your password');?>
- diff --git a/settings/templates/users.php b/settings/templates/users.php index e86dd46efbe..a6df85983dd 100644 --- a/settings/templates/users.php +++ b/settings/templates/users.php @@ -29,6 +29,11 @@ $_['subadmingroups'] = array_flip($items); + +
+ +
+
t('Default Storage'));?> diff --git a/settings/users.php b/settings/users.php index 94e6d0a9a10..e5c8a7aaa8d 100644 --- a/settings/users.php +++ b/settings/users.php @@ -20,6 +20,8 @@ $users = array(); $groups = array(); $isadmin = OC_User::isAdminUser(OC_User::getUser()); +$recoveryAdminEnabled = OC_App::isEnabled('files_encryption') && + OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' ); if($isadmin) { $accessiblegroups = OC_Group::getGroups(); @@ -77,4 +79,5 @@ $tmpl->assign( 'numofgroups', count($accessiblegroups)); $tmpl->assign( 'quota_preset', $quotaPreset); $tmpl->assign( 'default_quota', $defaultQuota); $tmpl->assign( 'defaultQuotaIsUserDefined', $defaultQuotaIsUserDefined); +$tmpl->assign( 'recoveryAdminEnabled', $recoveryAdminEnabled); $tmpl->printPage(); -- cgit v1.2.3 From 95297c246970f5e185b94cbc320b28d88a7c0d6d Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Thu, 16 May 2013 17:44:28 +0200 Subject: add pre-shared hooks --- lib/public/share.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'lib') diff --git a/lib/public/share.php b/lib/public/share.php index b2eeb29234a..e1538152d80 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1207,6 +1207,17 @@ class Share { if ($shareType == self::SHARE_TYPE_GROUP) { $groupItemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'], $uidOwner, $suggestedItemTarget); + \OC_Hook::emit('OCP\Share', 'pre_shared', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'itemTarget' => $groupItemTarget, + 'shareType' => $shareType, + 'shareWith' => $shareWith['group'], + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'fileSource' => $fileSource, + 'token' => $token + )); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { @@ -1282,6 +1293,17 @@ class Share { } else { $itemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $suggestedItemTarget); + \OC_Hook::emit('OCP\Share', 'pre_shared', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'itemTarget' => $itemTarget, + 'shareType' => $shareType, + 'shareWith' => $shareWith, + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'fileSource' => $fileSource, + 'token' => $token + )); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { -- cgit v1.2.3 From d7dc710c8b1d46947cb2afe13152e0adc9ee5594 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 17 May 2013 01:17:55 +0200 Subject: revert changes --- lib/public/share.php | 53 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/public/share.php b/lib/public/share.php index e1538152d80..03d662676c6 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1541,34 +1541,31 @@ class Share { } public static function post_addToGroup($arguments) { - - if(\OC_Config::getValue('installed')) { - // Find the group shares and check if the user needs a unique target - $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'); - $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'])); - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,' - .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,' - .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); - while ($item = $result->fetchRow()) { - if ($item['item_type'] == 'file' || $item['item_type'] == 'file') { - $itemTarget = null; - } else { - $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, - $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); - } - if (isset($item['file_source'])) { - $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, - $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); - } else { - $fileTarget = null; - } - // Insert an extra row for the group share if the item or file target is unique for this user - if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) { - $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], - self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], - $item['stime'], $item['file_source'], $fileTarget)); - \OC_DB::insertid('*PREFIX*share'); - } + // Find the group shares and check if the user needs a unique target + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'); + $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'])); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,' + .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,' + .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + while ($item = $result->fetchRow()) { + if ($item['item_type'] == 'file' || $item['item_type'] == 'file') { + $itemTarget = null; + } else { + $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); + } + if (isset($item['file_source'])) { + $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); + } else { + $fileTarget = null; + } + // Insert an extra row for the group share if the item or file target is unique for this user + if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) { + $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], + self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], + $item['stime'], $item['file_source'], $fileTarget)); + \OC_DB::insertid('*PREFIX*share'); } } } -- cgit v1.2.3 From 079f918d5ca0d242e77717aaeac82bcf011dc745 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sun, 19 May 2013 22:30:03 +0200 Subject: fix for webdav and wrong reference for findByStorageId --- lib/files/cache/backgroundwatcher.php | 2 +- lib/files/filesystem.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/files/cache/backgroundwatcher.php b/lib/files/cache/backgroundwatcher.php index 7549745e7d7..b5770d0582b 100644 --- a/lib/files/cache/backgroundwatcher.php +++ b/lib/files/cache/backgroundwatcher.php @@ -30,7 +30,7 @@ class BackgroundWatcher { return; } list($storageId, $internalPath) = $cacheItem; - $mounts = Mount::findByStorageId($storageId); + $mounts = Mount\Manager::findByStorageId($storageId); if (count($mounts) === 0) { //if the storage we need isn't mounted on default, try to find a user that has access to the storage diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d60d430d77c..d0cac9dc1d3 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -236,7 +236,9 @@ class Filesystem { } static public function initMounts(){ - self::$mounts = new Mount\Manager(); + if(!self::$mounts) { + self::$mounts = new Mount\Manager(); + } } /** -- cgit v1.2.3 From b3b6738d599480fc9bf40a53313598c4766571fb Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 20 May 2013 01:47:35 +0200 Subject: Revert "fix for webdav and wrong reference for findByStorageId" This reverts commit 079f918d5ca0d242e77717aaeac82bcf011dc745. --- lib/files/cache/backgroundwatcher.php | 2 +- lib/files/filesystem.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/files/cache/backgroundwatcher.php b/lib/files/cache/backgroundwatcher.php index b5770d0582b..7549745e7d7 100644 --- a/lib/files/cache/backgroundwatcher.php +++ b/lib/files/cache/backgroundwatcher.php @@ -30,7 +30,7 @@ class BackgroundWatcher { return; } list($storageId, $internalPath) = $cacheItem; - $mounts = Mount\Manager::findByStorageId($storageId); + $mounts = Mount::findByStorageId($storageId); if (count($mounts) === 0) { //if the storage we need isn't mounted on default, try to find a user that has access to the storage diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d0cac9dc1d3..d60d430d77c 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -236,9 +236,7 @@ class Filesystem { } static public function initMounts(){ - if(!self::$mounts) { - self::$mounts = new Mount\Manager(); - } + self::$mounts = new Mount\Manager(); } /** -- cgit v1.2.3 From 58a8d67a9b3c48567bcc40cc02444311c6773275 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 20 May 2013 01:57:16 +0200 Subject: fix for webdav because initMounts() is triggered twice so we lost the root path --- lib/files/filesystem.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d60d430d77c..d0cac9dc1d3 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -236,7 +236,9 @@ class Filesystem { } static public function initMounts(){ - self::$mounts = new Mount\Manager(); + if(!self::$mounts) { + self::$mounts = new Mount\Manager(); + } } /** -- cgit v1.2.3