Added method for setting user keyfile recovery preference

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
This commit is contained in:
Sam Tuke 2013-03-20 19:26:59 +01:00
parent c89fd49870
commit fd4e59b748
5 changed files with 127 additions and 32 deletions

View File

@ -40,7 +40,6 @@ class Hooks {
\OC\Files\Filesystem::init( $params['uid'] . '/' . 'files' . '/' ); \OC\Files\Filesystem::init( $params['uid'] . '/' . 'files' . '/' );
$view = new \OC_FilesystemView( '/' ); $view = new \OC_FilesystemView( '/' );
$util = new Util( $view, $params['uid'] ); $util = new Util( $view, $params['uid'] );
// Check files_encryption infrastructure is ready for action // Check files_encryption infrastructure is ready for action
@ -61,7 +60,6 @@ class Hooks {
$privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] );
$session = new Session(); $session = new Session();
$session->setPrivateKey( $privateKey, $params['uid'] ); $session->setPrivateKey( $privateKey, $params['uid'] );
$view1 = new \OC_FilesystemView( '/' . $params['uid'] ); $view1 = new \OC_FilesystemView( '/' . $params['uid'] );

View File

@ -57,6 +57,7 @@ class Keymanager {
return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' );
\OC_FileProxy::$enabled = true; \OC_FileProxy::$enabled = true;
} }
/** /**

View File

@ -131,10 +131,37 @@ class Proxy extends \OC_FileProxy {
// Encrypt data // Encrypt data
$encData = Crypt::symmetricEncryptFileContent( $data, $plainKey ); $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey );
// Check if the keyfile needs to be shared // Check if key recovery is enabled
if ( $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ) ) { $recoveryEnabled = $util->recoveryEnabled();
$publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); // 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 );
$userIds = array_merge( $userIds, $shareUids );
}
// If recovery is enabled, add the
// Admin UID to list of users to share to
if ( $recoveryEnabled ) {
// 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; \OC_FileProxy::$enabled = false;
@ -146,16 +173,7 @@ class Proxy extends \OC_FileProxy {
Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
// Set encrypted keyfile as common varname // Set encrypted keyfile as common varname
$encKey = $multiEncrypted['encrypted']; $encKey = $multiEncrypted['data'];
} else {
$publicKey = Keymanager::getPublicKey( $rootView, $userId );
// Encrypt plain data to a single user
$encKey = Crypt::keyEncrypt( $plainKey, $publicKey );
}
// Save the key if its new // Save the key if its new
if ( ! $keyPreExists ) { if ( ! $keyPreExists ) {

View File

@ -31,7 +31,12 @@
# ---------------- # ----------------
# Re-use existing keyfiles so they don't need version control (part implemented, stream{} and util{} remain) # 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 # 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: // Old Todo:
@ -202,16 +207,69 @@ class Util {
} }
/**
* @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() { public function recoveryEnabled() {
$sql = 'SELECT * FROM `*PREFIX*myusers` WHERE id = ?'; $sql = 'SELECT
$args = array(1); recovery
FROM
`*PREFIX*encryption`
WHERE
uid = ?';
$args = array( $this->userId );
$query = \OCP\DB::prepare( $sql ); $query = \OCP\DB::prepare( $sql );
$result = $query->execute( $args ); $result = $query->execute( $args );
// Set default in case no records found
$recoveryEnabled = 0;
while( $row = $result->fetchRow() ) { while( $row = $result->fetchRow() ) {
$userName = $row['username'];
$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;
} }
} }

View File

@ -165,6 +165,26 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
} }
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 // * @brief test decryption using legacy blowfish method
// * @depends testLegacyEncryptLong // * @depends testLegacyEncryptLong