|
|
|
|
@ -27,63 +27,77 @@ namespace OCA\Encryption; |
|
|
|
|
* @note Where a method requires a view object, it's root must be '/' |
|
|
|
|
*/ |
|
|
|
|
class Keymanager { |
|
|
|
|
|
|
|
|
|
# TODO: make all dependencies (including static classes) explicit, such as ocfsview objects, by adding them as method arguments (dependency injection) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: make all dependencies (including static classes) explicit, such as ocfsview objects, |
|
|
|
|
// by adding them as method arguments (dependency injection) |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief retrieve the ENCRYPTED private key from a user |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* @param \OC_FilesystemView $view |
|
|
|
|
* @param $user |
|
|
|
|
* @return string private key or false |
|
|
|
|
* @note the key returned by this method must be decrypted before use |
|
|
|
|
*/ |
|
|
|
|
public static function getPrivateKey( \OC_FilesystemView $view, $user ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$path = '/' . $user . '/' . 'files_encryption' . '/' . $user.'.private.key'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$key = $view->file_get_contents( $path ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $key; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief retrieve public key for a specified user |
|
|
|
|
* @param \OC_FilesystemView $view |
|
|
|
|
* @param $userId |
|
|
|
|
* @return string public key or false |
|
|
|
|
*/ |
|
|
|
|
public static function getPublicKey( \OC_FilesystemView $view, $userId ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief retrieve both keys from a user (private and public) |
|
|
|
|
* @param \OC_FilesystemView $view |
|
|
|
|
* @param $userId |
|
|
|
|
* @return array keys: privateKey, publicKey |
|
|
|
|
*/ |
|
|
|
|
public static function getUserKeys( \OC_FilesystemView $view, $userId ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return array( |
|
|
|
|
'publicKey' => self::getPublicKey( $view, $userId ) |
|
|
|
|
, 'privateKey' => self::getPrivateKey( $view, $userId ) |
|
|
|
|
, 'privateKey' => self::getPrivateKey( $view, $userId ) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief Retrieve public keys of all users with access to a file |
|
|
|
|
* @param string $path Path to file |
|
|
|
|
* @param \OC_FilesystemView $view |
|
|
|
|
* @param $userId |
|
|
|
|
* @param $filePath |
|
|
|
|
* @internal param string $path Path to file |
|
|
|
|
* @return array of public keys for the given file |
|
|
|
|
* @note Checks that the sharing app is enabled should be performed |
|
|
|
|
* @note Checks that the sharing app is enabled should be performed |
|
|
|
|
* by client code, that isn't checked here |
|
|
|
|
*/ |
|
|
|
|
public static function getPublicKeys( \OC_FilesystemView $view, $userId, $filePath ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// |
|
|
|
|
// TODO: UNDEFINED VARIABLE: $path |
|
|
|
|
// |
|
|
|
|
|
|
|
|
|
$path = ltrim( $path, '/' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$filepath = '/' . $userId . '/files/' . $filePath; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if sharing is enabled |
|
|
|
|
if ( OC_App::isEnabled( 'files_sharing' ) ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Check if file was shared with other users |
|
|
|
|
// $query = \OC_DB::prepare( " |
|
|
|
|
// SELECT |
|
|
|
|
@ -116,45 +130,48 @@ class Keymanager { |
|
|
|
|
// } |
|
|
|
|
// |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check if it is a file owned by the user and not shared at all |
|
|
|
|
$userview = new \OC_FilesystemView( '/'.$userId.'/files/' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( $userview->file_exists( $path ) ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$users[] = $userId; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$view = new \OC_FilesystemView( '/public-keys/' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$keylist = array(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$count = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach ( $users as $user ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$keylist['key'.++$count] = $view->file_get_contents( $user.'.public.key' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $keylist; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief retrieve keyfile for an encrypted file |
|
|
|
|
* @param string file name |
|
|
|
|
* @param \OC_FilesystemView $view |
|
|
|
|
* @param $userId |
|
|
|
|
* @param $filePath |
|
|
|
|
* @internal param \OCA\Encryption\file $string name |
|
|
|
|
* @return string file key or false |
|
|
|
|
* @note The keyfile returned is asymmetrically encrypted. Decryption |
|
|
|
|
* of the keyfile must be performed by client code |
|
|
|
|
*/ |
|
|
|
|
public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$filePath_f = ltrim( $filePath, '/' ); |
|
|
|
|
|
|
|
|
|
// // update $keypath and $userId if path point to a file shared by someone else |
|
|
|
|
@ -172,17 +189,19 @@ class Keymanager { |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
return $view->file_get_contents( '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief retrieve file encryption key |
|
|
|
|
* |
|
|
|
|
* @param string file name |
|
|
|
|
* @param $path |
|
|
|
|
* @param string $staticUserClass |
|
|
|
|
* @internal param \OCA\Encryption\file $string name |
|
|
|
|
* @return string file key or false |
|
|
|
|
*/ |
|
|
|
|
public static function deleteFileKey( $path, $staticUserClass = 'OCP\User' ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$keypath = ltrim( $path, '/' ); |
|
|
|
|
$user = $staticUserClass::getUser(); |
|
|
|
|
|
|
|
|
|
@ -199,13 +218,13 @@ class Keymanager { |
|
|
|
|
// $keypath = str_replace( '/' . $user . '/files/', '', $keypath ); |
|
|
|
|
// |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$view = new \OC_FilesystemView('/'.$user.'/files_encryption/keyfiles/'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $view->unlink( $keypath . '.key' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief store private key from the user |
|
|
|
|
* @param string key |
|
|
|
|
@ -214,21 +233,25 @@ class Keymanager { |
|
|
|
|
* as no encryption takes place here |
|
|
|
|
*/ |
|
|
|
|
public static function setPrivateKey( $key ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$user = \OCP\User::getUser(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$view = new \OC_FilesystemView( '/' . $user . '/files_encryption' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\OC_FileProxy::$enabled = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $view->file_put_contents( $user . '.private.key', $key ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// |
|
|
|
|
// TODO: UNREACHABLE CODE |
|
|
|
|
// |
|
|
|
|
|
|
|
|
|
\OC_FileProxy::$enabled = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief store private keys from the user |
|
|
|
|
* |
|
|
|
|
@ -237,11 +260,11 @@ class Keymanager { |
|
|
|
|
* @return bool true/false |
|
|
|
|
*/ |
|
|
|
|
public static function setUserKeys($privatekey, $publickey) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (self::setPrivateKey($privatekey) && self::setPublicKey($publickey)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief store public key of the user |
|
|
|
|
* |
|
|
|
|
@ -249,33 +272,38 @@ class Keymanager { |
|
|
|
|
* @return bool true/false |
|
|
|
|
*/ |
|
|
|
|
public static function setPublicKey( $key ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$view = new \OC_FilesystemView( '/public-keys' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\OC_FileProxy::$enabled = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $view->file_put_contents( \OCP\User::getUser() . '.public.key', $key ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// |
|
|
|
|
// TODO: UNREACHED CODE !!! |
|
|
|
|
// |
|
|
|
|
\OC_FileProxy::$enabled = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief store file encryption key |
|
|
|
|
* |
|
|
|
|
* @param string $path relative path of the file, including filename |
|
|
|
|
* @param string $key |
|
|
|
|
* @param null $view |
|
|
|
|
* @param string $dbClassName |
|
|
|
|
* @return bool true/false |
|
|
|
|
* @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 |
|
|
|
|
*/ |
|
|
|
|
public static function setFileKey( $path, $key, $view = Null, $dbClassName = '\OC_DB') { |
|
|
|
|
|
|
|
|
|
$targetPath = ltrim( $path, '/' ); |
|
|
|
|
$user = \OCP\User::getUser(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // update $keytarget and $user 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 = ?" ); |
|
|
|
|
// |
|
|
|
|
@ -304,32 +332,32 @@ class Keymanager { |
|
|
|
|
// //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'] ) |
|
|
|
|
if ( |
|
|
|
|
isset( $path_parts['dirname'] ) |
|
|
|
|
&& ! $view->file_exists( $path_parts['dirname'] ) |
|
|
|
|
) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$view->mkdir( $path_parts['dirname'] ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Save the keyfile in parallel directory |
|
|
|
|
return $view->file_put_contents( '/' . $targetPath . '.key', $key ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief change password of private encryption key |
|
|
|
|
* |
|
|
|
|
@ -338,28 +366,28 @@ class Keymanager { |
|
|
|
|
* @return bool true/false |
|
|
|
|
*/ |
|
|
|
|
public static function changePasswd($oldpasswd, $newpasswd) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( \OCP\User::checkPassword(\OCP\User::getUser(), $newpasswd) ) { |
|
|
|
|
return Crypt::changekeypasscode($oldpasswd, $newpasswd); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief Fetch the legacy encryption key from user files |
|
|
|
|
* @param string $login used to locate the legacy key |
|
|
|
|
* @param string $passphrase used to decrypt the legacy key |
|
|
|
|
* @internal param string $login used to locate the legacy key |
|
|
|
|
* @internal param string $passphrase used to decrypt the legacy key |
|
|
|
|
* @return true / false |
|
|
|
|
* |
|
|
|
|
* if the key is left out, the default handeler will be used |
|
|
|
|
*/ |
|
|
|
|
public function getLegacyKey() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$user = \OCP\User::getUser(); |
|
|
|
|
$view = new \OC_FilesystemView( '/' . $user ); |
|
|
|
|
return $view->file_get_contents( 'encryption.key' ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|