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