]> source.dussan.org Git - nextcloud-server.git/commitdiff
Added method for setting user keyfile recovery preference
authorSam Tuke <samtuke@owncloud.com>
Wed, 20 Mar 2013 18:26:59 +0000 (19:26 +0100)
committerSam Tuke <samtuke@owncloud.com>
Wed, 20 Mar 2013 18:26:59 +0000 (19:26 +0100)
Fixed method for checking if keyfile recovery is enabled for a user
Added unit test for above 2 methods
Made proxy{} always use sharing
Made proxy{} work regardless of sharing API enabled or not
Implemented proxy-based sharing to admin if user keyfile recovery is enabled

apps/files_encryption/hooks/hooks.php
apps/files_encryption/lib/keymanager.php
apps/files_encryption/lib/proxy.php
apps/files_encryption/lib/util.php
apps/files_encryption/test/util.php

index 8db75397063153b976908a3b049be191aa843820..82e650c417c31ce9597ee90c9e6a2cf23474d55c 100644 (file)
@@ -40,7 +40,6 @@ class Hooks {
                \OC\Files\Filesystem::init( $params['uid'] . '/' . 'files' . '/' );\r
        \r
                $view = new \OC_FilesystemView( '/' );\r
-\r
                $util = new Util( $view, $params['uid'] );\r
                \r
                // Check files_encryption infrastructure is ready for action\r
@@ -61,7 +60,6 @@ class Hooks {
                $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] );\r
                \r
                $session = new Session();\r
-               \r
                $session->setPrivateKey( $privateKey, $params['uid'] );\r
                \r
                $view1 = new \OC_FilesystemView( '/' . $params['uid'] );\r
index 0c2db2be32904a0291e37c850e812dcdfe5ccf2d..6837dcf67b5cee743192605943e26ee9c71f0812 100755 (executable)
@@ -57,6 +57,7 @@ class Keymanager {
                return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' );\r
                \r
                \OC_FileProxy::$enabled = true;\r
+               \r
        }\r
        \r
        /**\r
index 2a738c80e388d43644da3978be9321cdc4b1d904..f469422e225aef9f75237bf3d7646842e8af8410 100644 (file)
@@ -131,32 +131,50 @@ class Proxy extends \OC_FileProxy {
                                // Encrypt data
                                $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey );
                                
-                               // Check if the keyfile needs to be shared
-                               if ( $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ) ) {
-                                       
-                                       $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds );
-                                       
-                                       \OC_FileProxy::$enabled = false;
-                                       
-                                       // Encrypt plain keyfile to multiple sharefiles
-                                       $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
-                                       
-                                       // Save sharekeys to user folders
-                                       // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones
-                                       Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
+                               // Check if key recovery is enabled
+                               $recoveryEnabled = $util->recoveryEnabled();
+                               
+                               // Make sure that a share key is generated for the owner too
+                               $userIds = array( $userId );
+                               
+                               if ( \OCP\Share::isEnabled() ) {
+                               
+                                       // Find out who, if anyone, is sharing the file
+                                       $shareUids = \OCP\Share::getUsersSharingFile( $filePath, true );
                                        
-                                       // Set encrypted keyfile as common varname
-                                       $encKey = $multiEncrypted['encrypted'];
+                                       $userIds = array_merge( $userIds, $shareUids );
                                
-                               } else {
+                               }
                                
-                                       $publicKey = Keymanager::getPublicKey( $rootView, $userId );
+                               // If recovery is enabled, add the 
+                               // Admin UID to list of users to share to
+                               if ( $recoveryEnabled ) {
                                
-                                       // Encrypt plain data to a single user
-                                       $encKey = Crypt::keyEncrypt( $plainKey, $publicKey );
+                                       // FIXME: Create a separate admin user purely for recovery, and create method in util for fetching this id from DB?
+                                       $adminUid = 'recoveryAdmin';
                                
+                                       $userIds[] = $adminUid;
+                                       
                                }
                                
+                               // Remove duplicate UIDs
+                               $uniqueUserIds = array_unique ( $userIds );
+                               
+                               // 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
+                               $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
+                               
+                               // Save sharekeys to user folders
+                               // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones
+                               Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
+                               
+                               // Set encrypted keyfile as common varname
+                               $encKey = $multiEncrypted['data'];
+                               
                                // Save the key if its new
                                if ( ! $keyPreExists ) {
                                
index a80da73a4b0c26e22d11ce38560f4ccbde6168b8..b86e7f421b86a70b2adf618b2e416bad2cb6de53 100644 (file)
 # ----------------
 # Re-use existing keyfiles so they don't need version control (part implemented, stream{} and util{} remain)
 # Make sure user knows if large files weren't encrypted
-# Trashbin support
+
+
+# Test
+# ----
+# Test that writing files works when recovery is enabled, and sharing API is disabled
+# Test trashbin support
 
 
 // Old Todo:
@@ -202,18 +207,71 @@ class Util {
        
        }
        
-       public function recoveryEnabled(  ) {
+       /**
+        * @brief Check whether pwd recovery is enabled for a given user
+        * @return bool
+        * @note If records are not being returned, check for a hidden space 
+        *       at the start of the uid in db
+        */
+       public function recoveryEnabled() {
        
-               $sql = 'SELECT * FROM `*PREFIX*myusers` WHERE id = ?';
-               $args = array(1);
-
-               $query = \OCP\DB::prepare($sql);
-               $result = $query->execute($args);
+               $sql = 'SELECT 
+                               recovery 
+                       FROM 
+                               `*PREFIX*encryption` 
+                       WHERE 
+                               uid = ?';
+                               
+               $args = array( $this->userId );
 
-               while($row = $result->fetchRow()) {
-                       $userName = $row['username'];
-               }       
+               $query = \OCP\DB::prepare( $sql );
+               
+               $result = $query->execute( $args );
+               
+               // Set default in case no records found
+               $recoveryEnabled = 0;
+               
+               while( $row = $result->fetchRow() ) {
+               
+                       $recoveryEnabled = $row['recovery'];
+                       
+               }
+               
+               return $recoveryEnabled;
+       
+       }
        
+       /**
+        * @brief Enable / disable pwd recovery for a given user
+        * @param bool $enabled Whether to enable or disable recovery
+        * @return bool
+        */
+       public function setRecovery( $enabled ) {
+       
+               $sql = 'UPDATE 
+                               *PREFIX*encryption 
+                       SET 
+                               recovery = ? 
+                       WHERE 
+                               uid = ?';
+               
+               // Ensure value is an integer
+               $enabled = intval( $enabled );
+               
+               $args = array( $enabled, $this->userId );
+
+               $query = \OCP\DB::prepare( $sql );
+               
+               if ( $query->execute( $args ) ) {
+               
+                       return true;
+                       
+               } else {
+               
+                       return false;
+                       
+               }
+               
        }
        
        /**
index 275e60f4bd62a128faa1142eee4351a95318a26d..e2767a2ec39fccb84f6f21b44acdf9ad6e032ea1 100755 (executable)
@@ -164,6 +164,26 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
                # then false will be returned. Use strict ordering?
                
        }
+       
+       function testRecoveryEnabled() {
+               
+               $util = new Encryption\Util( $this->view, $this->userId );
+               
+               // Record the value so we can return it to it's original state later
+               $enabled = $util->recoveryEnabled();
+               
+               $this->assertTrue( $util->setRecovery( 1 ) );
+               
+               $this->assertEquals( 1, $util->recoveryEnabled() );
+               
+               $this->assertTrue( $util->setRecovery( 0 ) );
+               
+               $this->assertEquals( 0, $util->recoveryEnabled() );
+               
+               // Return the setting to it's previous state
+               $this->assertTrue( $util->setRecovery( $enabled ) );
+               
+       }
 
 //     /**
 //      * @brief test decryption using legacy blowfish method