2012-07-11 20:51:27 +04:00
|
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* ownCloud
|
|
|
|
|
*
|
|
|
|
|
* @author Sam Tuke, Frank Karlitschek
|
|
|
|
|
* @copyright 2012 Sam Tuke samtuke@owncloud.com,
|
|
|
|
|
* Frank Karlitschek frank@owncloud.org
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 3 of the License, or any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Affero General Public
|
|
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Todo:
|
|
|
|
|
// - Crypt/decrypt button in the userinterface
|
|
|
|
|
// - Setting if crypto should be on by default
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// - Add a setting "Don´t encrypt files larger than xx because of performance
|
|
|
|
|
// reasons"
|
|
|
|
|
// - Transparent decrypt/encrypt in filesystem.php. Autodetect if a file is
|
|
|
|
|
// encrypted (.encrypted extension)
|
|
|
|
|
// - Don't use a password directly as encryption key. but a key which is
|
|
|
|
|
// stored on the server and encrypted with the user password. -> password
|
|
|
|
|
// change faster
|
2012-07-11 20:51:27 +04:00
|
|
|
|
// - IMPORTANT! Check if the block lenght of the encrypted data stays the same
|
|
|
|
|
|
2012-10-17 19:35:19 +04:00
|
|
|
|
namespace OCA\Encryption;
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
/**
|
2012-07-25 18:33:25 +04:00
|
|
|
|
* @brief Class for utilities relating to encrypted file storage system
|
2013-01-31 23:40:51 +04:00
|
|
|
|
* @param OC_FilesystemView $view expected to have OC '/' as root path
|
|
|
|
|
* @param string $userId ID of the logged in user
|
|
|
|
|
* @param int $client indicating status of client side encryption. Currently
|
2012-07-25 18:33:25 +04:00
|
|
|
|
* unused, likely to become obsolete shortly
|
2012-07-11 20:51:27 +04:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
class Util {
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// Web UI:
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
//// DONE: files created via web ui are encrypted
|
|
|
|
|
//// DONE: file created & encrypted via web ui are readable in web ui
|
|
|
|
|
//// DONE: file created & encrypted via web ui are readable via webdav
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// WebDAV:
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
//// DONE: new data filled files added via webdav get encrypted
|
|
|
|
|
//// DONE: new data filled files added via webdav are readable via webdav
|
|
|
|
|
//// DONE: reading unencrypted files when encryption is enabled works via
|
|
|
|
|
//// webdav
|
|
|
|
|
//// DONE: files created & encrypted via web ui are readable via webdav
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// Legacy support:
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
//// DONE: add method to check if file is encrypted using new system
|
|
|
|
|
//// DONE: add method to check if file is encrypted using old system
|
|
|
|
|
//// DONE: add method to fetch legacy key
|
|
|
|
|
//// DONE: add method to decrypt legacy encrypted data
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// Admin UI:
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
//// DONE: changing user password also changes encryption passphrase
|
2012-12-11 21:12:46 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
//// TODO: add support for optional recovery in case of lost passphrase / keys
|
|
|
|
|
//// TODO: add admin optional required long passphrase for users
|
|
|
|
|
//// TODO: add UI buttons for encrypt / decrypt everything
|
|
|
|
|
//// TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc.
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// Sharing:
|
2012-12-11 21:12:46 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
//// TODO: add support for encrypting to multiple public keys
|
|
|
|
|
//// TODO: add support for decrypting to multiple private keys
|
2012-12-11 21:12:46 +04:00
|
|
|
|
|
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// Integration testing:
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
//// TODO: test new encryption with versioning
|
|
|
|
|
//// TODO: test new encryption with sharing
|
|
|
|
|
//// TODO: test new encryption with proxies
|
2012-12-04 23:53:13 +04:00
|
|
|
|
|
2012-11-22 18:08:19 +04:00
|
|
|
|
|
2012-07-11 20:51:27 +04:00
|
|
|
|
private $view; // OC_FilesystemView object for filesystem operations
|
2013-01-23 23:24:26 +04:00
|
|
|
|
private $userId; // ID of the currently logged-in user
|
2012-07-11 20:51:27 +04:00
|
|
|
|
private $pwd; // User Password
|
|
|
|
|
private $client; // Client side encryption mode flag
|
2013-01-14 19:39:04 +04:00
|
|
|
|
private $publicKeyDir; // Dir containing all public user keys
|
|
|
|
|
private $encryptionDir; // Dir containing user's files_encryption
|
|
|
|
|
private $keyfilesPath; // Dir containing user's keyfiles
|
|
|
|
|
private $shareKeysPath; // Dir containing env keys for shared files
|
2012-11-16 22:31:37 +04:00
|
|
|
|
private $publicKeyPath; // Path to user's public key
|
|
|
|
|
private $privateKeyPath; // Path to user's private key
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
public function __construct( \OC_FilesystemView $view, $userId, $client = false ) {
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
$this->view = $view;
|
2012-07-25 18:33:25 +04:00
|
|
|
|
$this->userId = $userId;
|
2012-07-11 20:51:27 +04:00
|
|
|
|
$this->client = $client;
|
2013-01-23 23:24:26 +04:00
|
|
|
|
$this->userDir = '/' . $this->userId;
|
|
|
|
|
$this->userFilesDir = '/' . $this->userId . '/' . 'files';
|
2012-07-25 18:33:25 +04:00
|
|
|
|
$this->publicKeyDir = '/' . 'public-keys';
|
|
|
|
|
$this->encryptionDir = '/' . $this->userId . '/' . 'files_encryption';
|
|
|
|
|
$this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
|
2013-01-14 19:39:04 +04:00
|
|
|
|
$this->shareKeysPath = $this->encryptionDir . '/' . 'share-keys';
|
2012-07-25 18:33:25 +04:00
|
|
|
|
$this->publicKeyPath = $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key
|
|
|
|
|
$this->privateKeyPath = $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function ready() {
|
|
|
|
|
|
|
|
|
|
if(
|
2013-01-23 23:24:26 +04:00
|
|
|
|
!$this->view->file_exists( $this->encryptionDir )
|
|
|
|
|
or !$this->view->file_exists( $this->keyfilesPath )
|
|
|
|
|
or !$this->view->file_exists( $this->shareKeysPath )
|
2012-07-25 18:33:25 +04:00
|
|
|
|
or !$this->view->file_exists( $this->publicKeyPath )
|
|
|
|
|
or !$this->view->file_exists( $this->privateKeyPath )
|
2012-07-11 20:51:27 +04:00
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-24 20:53:12 +04:00
|
|
|
|
/**
|
2012-07-25 18:33:25 +04:00
|
|
|
|
* @brief Sets up user folders and keys for serverside encryption
|
2012-07-24 20:53:12 +04:00
|
|
|
|
* @param $passphrase passphrase to encrypt server-stored private key with
|
|
|
|
|
*/
|
2012-07-25 18:33:25 +04:00
|
|
|
|
public function setupServerSide( $passphrase = null ) {
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// Create user dir
|
|
|
|
|
if( !$this->view->file_exists( $this->userDir ) ) {
|
|
|
|
|
|
|
|
|
|
$this->view->mkdir( $this->userDir );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create user files dir
|
|
|
|
|
if( !$this->view->file_exists( $this->userFilesDir ) ) {
|
|
|
|
|
|
|
|
|
|
$this->view->mkdir( $this->userFilesDir );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
// Create shared public key directory
|
|
|
|
|
if( !$this->view->file_exists( $this->publicKeyDir ) ) {
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
$this->view->mkdir( $this->publicKeyDir );
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
// Create encryption app directory
|
|
|
|
|
if( !$this->view->file_exists( $this->encryptionDir ) ) {
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
$this->view->mkdir( $this->encryptionDir );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create mirrored keyfile directory
|
|
|
|
|
if( !$this->view->file_exists( $this->keyfilesPath ) ) {
|
|
|
|
|
|
|
|
|
|
$this->view->mkdir( $this->keyfilesPath );
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
}
|
2013-01-14 19:39:04 +04:00
|
|
|
|
|
|
|
|
|
// Create mirrored share env keys directory
|
|
|
|
|
if( !$this->view->file_exists( $this->shareKeysPath ) ) {
|
|
|
|
|
|
|
|
|
|
$this->view->mkdir( $this->shareKeysPath );
|
|
|
|
|
|
|
|
|
|
}
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
// Create user keypair
|
|
|
|
|
if (
|
2013-01-24 22:37:34 +04:00
|
|
|
|
! $this->view->file_exists( $this->publicKeyPath )
|
|
|
|
|
or ! $this->view->file_exists( $this->privateKeyPath )
|
2012-07-11 20:51:27 +04:00
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
// Generate keypair
|
|
|
|
|
$keypair = Crypt::createKeypair();
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
\OC_FileProxy::$enabled = false;
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
// Save public key
|
2012-07-25 18:33:25 +04:00
|
|
|
|
$this->view->file_put_contents( $this->publicKeyPath, $keypair['publicKey'] );
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
// Encrypt private key with user pwd as passphrase
|
|
|
|
|
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], $passphrase );
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
// Save private key
|
|
|
|
|
$this->view->file_put_contents( $this->privateKeyPath, $encryptedPrivateKey );
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
2012-07-25 18:33:25 +04:00
|
|
|
|
\OC_FileProxy::$enabled = true;
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
}
|
2012-11-16 22:31:37 +04:00
|
|
|
|
|
|
|
|
|
return true;
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
}
|
2012-07-24 20:53:12 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Find all files and their encryption status within a directory
|
|
|
|
|
* @param string $directory The path of the parent directory to search
|
|
|
|
|
* @return mixed false if 0 found, array on success. Keys: name, path
|
2013-01-29 23:54:40 +04:00
|
|
|
|
|
|
|
|
|
* @note $directory needs to be a path relative to OC data dir. e.g.
|
|
|
|
|
* /admin/files NOT /backup OR /home/www/oc/data/admin/files
|
2013-01-23 23:24:26 +04:00
|
|
|
|
*/
|
|
|
|
|
public function findFiles( $directory ) {
|
|
|
|
|
|
|
|
|
|
// Disable proxy - we don't want files to be decrypted before
|
|
|
|
|
// we handle them
|
|
|
|
|
\OC_FileProxy::$enabled = false;
|
|
|
|
|
|
|
|
|
|
$found = array( 'plain' => array(), 'encrypted' => array(), 'legacy' => array() );
|
|
|
|
|
|
|
|
|
|
if (
|
2013-01-24 22:37:34 +04:00
|
|
|
|
$this->view->is_dir( $directory )
|
|
|
|
|
&& $handle = $this->view->opendir( $directory )
|
2013-01-23 23:24:26 +04:00
|
|
|
|
) {
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
|
|
|
|
while ( false !== ( $file = readdir( $handle ) ) ) {
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
2012-07-31 22:28:11 +04:00
|
|
|
|
if (
|
|
|
|
|
$file != "."
|
|
|
|
|
&& $file != ".."
|
|
|
|
|
) {
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
$filePath = $directory . '/' . $this->view->getRelativePath( '/' . $file );
|
2013-02-05 19:59:28 +04:00
|
|
|
|
$relPath = $this->stripUserFilesPath( $filePath );
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// If the path is a directory, search
|
|
|
|
|
// its contents
|
2012-07-31 22:28:11 +04:00
|
|
|
|
if ( $this->view->is_dir( $filePath ) ) {
|
|
|
|
|
|
|
|
|
|
$this->findFiles( $filePath );
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// If the path is a file, determine
|
|
|
|
|
// its encryption status
|
|
|
|
|
} elseif ( $this->view->is_file( $filePath ) ) {
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// Disable proxies again, some-
|
2013-01-31 23:40:51 +04:00
|
|
|
|
// where they got re-enabled :/
|
2013-01-23 23:24:26 +04:00
|
|
|
|
\OC_FileProxy::$enabled = false;
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-31 23:40:51 +04:00
|
|
|
|
$data = $this->view->file_get_contents( $filePath );
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// If the file is encrypted
|
2013-01-31 23:40:51 +04:00
|
|
|
|
// NOTE: If the userId is
|
|
|
|
|
// empty or not set, file will
|
|
|
|
|
// detected as plain
|
2013-02-01 23:31:15 +04:00
|
|
|
|
// NOTE: This is inefficient;
|
|
|
|
|
// scanning every file like this
|
|
|
|
|
// will eat server resources :(
|
2013-01-31 23:40:51 +04:00
|
|
|
|
if (
|
|
|
|
|
Keymanager::getFileKey( $this->view, $this->userId, $file )
|
2013-02-06 18:30:40 +04:00
|
|
|
|
&& Crypt::isCatfile( $data )
|
2013-01-31 23:40:51 +04:00
|
|
|
|
) {
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
$found['encrypted'][] = array( 'name' => $file, 'path' => $filePath );
|
|
|
|
|
|
|
|
|
|
// If the file uses old
|
|
|
|
|
// encryption system
|
2013-02-05 19:59:28 +04:00
|
|
|
|
} elseif ( Crypt::isLegacyEncryptedContent( $this->view->file_get_contents( $filePath ), $relPath ) ) {
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
$found['legacy'][] = array( 'name' => $file, 'path' => $filePath );
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// If the file is not encrypted
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
$found['plain'][] = array( 'name' => $file, 'path' => $filePath );
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
\OC_FileProxy::$enabled = true;
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
if ( empty( $found ) ) {
|
|
|
|
|
|
|
|
|
|
return false;
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
|
|
|
|
} else {
|
2013-01-29 23:54:40 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
return $found;
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
\OC_FileProxy::$enabled = true;
|
|
|
|
|
|
2012-07-31 22:28:11 +04:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-17 19:35:19 +04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Check if a given path identifies an encrypted file
|
|
|
|
|
* @return true / false
|
|
|
|
|
*/
|
|
|
|
|
public function isEncryptedPath( $path ) {
|
|
|
|
|
|
2012-12-04 23:53:13 +04:00
|
|
|
|
// Disable encryption proxy so data retreived is in its
|
|
|
|
|
// original form
|
|
|
|
|
\OC_FileProxy::$enabled = false;
|
|
|
|
|
|
2012-10-17 19:35:19 +04:00
|
|
|
|
$data = $this->view->file_get_contents( $path );
|
|
|
|
|
|
2012-12-04 23:53:13 +04:00
|
|
|
|
\OC_FileProxy::$enabled = true;
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
return Crypt::isCatfile( $data );
|
2012-10-17 19:35:19 +04:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-05 19:59:28 +04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Format a path to be relative to the /user/files/ directory
|
|
|
|
|
*/
|
|
|
|
|
public function stripUserFilesPath( $path ) {
|
|
|
|
|
|
|
|
|
|
$trimmed = ltrim( $path, '/' );
|
|
|
|
|
$split = explode( '/', $trimmed );
|
|
|
|
|
$sliced = array_slice( $split, 2 );
|
|
|
|
|
$relPath = implode( '/', $sliced );
|
|
|
|
|
|
|
|
|
|
return $relPath;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Encrypt all files in a directory
|
|
|
|
|
* @param string $publicKey the public key to encrypt files with
|
|
|
|
|
* @param string $dirPath the directory whose files will be encrypted
|
|
|
|
|
* @note Encryption is recursive
|
|
|
|
|
*/
|
2013-01-24 22:37:34 +04:00
|
|
|
|
public function encryptAll( $publicKey, $dirPath, $legacyPassphrase = null, $newPassphrase = null ) {
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
if ( $found = $this->findFiles( $dirPath ) ) {
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-29 23:54:40 +04:00
|
|
|
|
// Disable proxy to prevent file being encrypted twice
|
|
|
|
|
\OC_FileProxy::$enabled = false;
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// Encrypt unencrypted files
|
2013-01-29 23:54:40 +04:00
|
|
|
|
foreach ( $found['plain'] as $plainFile ) {
|
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// Fetch data from file
|
2013-01-29 23:54:40 +04:00
|
|
|
|
$plainData = $this->view->file_get_contents( $plainFile['path'] );
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
|
|
|
|
// Encrypt data, generate catfile
|
|
|
|
|
$encrypted = Crypt::keyEncryptKeyfile( $plainData, $publicKey );
|
|
|
|
|
|
2013-02-05 19:59:28 +04:00
|
|
|
|
$relPath = $this->stripUserFilesPath( $plainFile['path'] );
|
2013-01-29 23:54:40 +04:00
|
|
|
|
|
2013-01-31 23:40:51 +04:00
|
|
|
|
// Save keyfile
|
2013-01-29 23:54:40 +04:00
|
|
|
|
Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encrypted['key'] );
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
|
|
|
|
// Overwrite the existing file with the encrypted one
|
2013-01-29 23:54:40 +04:00
|
|
|
|
$this->view->file_put_contents( $plainFile['path'], $encrypted['data'] );
|
2013-01-31 23:40:51 +04:00
|
|
|
|
|
|
|
|
|
$size = strlen( $encrypted['data'] );
|
|
|
|
|
|
|
|
|
|
// Add the file to the cache
|
|
|
|
|
\OC\Files\Filesystem::putFileInfo( $plainFile['path'], array( 'encrypted'=>true, 'size' => $size ), '' );
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
|
|
|
|
}
|
2012-07-31 22:28:11 +04:00
|
|
|
|
|
2013-01-23 23:24:26 +04:00
|
|
|
|
// Encrypt legacy encrypted files
|
2013-01-24 22:37:34 +04:00
|
|
|
|
if (
|
|
|
|
|
! empty( $legacyPassphrase )
|
|
|
|
|
&& ! empty( $newPassphrase )
|
|
|
|
|
) {
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
2013-02-05 19:35:29 +04:00
|
|
|
|
foreach ( $found['legacy'] as $legacyFile ) {
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
2013-01-24 22:37:34 +04:00
|
|
|
|
// Fetch data from file
|
2013-02-05 19:35:29 +04:00
|
|
|
|
$legacyData = $this->view->file_get_contents( $legacyFile['path'] );
|
2013-01-24 22:37:34 +04:00
|
|
|
|
|
|
|
|
|
// Recrypt data, generate catfile
|
|
|
|
|
$recrypted = Crypt::legacyKeyRecryptKeyfile( $legacyData, $legacyPassphrase, $publicKey, $newPassphrase );
|
|
|
|
|
|
2013-02-05 19:59:28 +04:00
|
|
|
|
$relPath = $this->stripUserFilesPath( $legacyFile['path'] );
|
2013-02-05 19:35:29 +04:00
|
|
|
|
|
2013-01-31 23:40:51 +04:00
|
|
|
|
// Save keyfile
|
2013-02-05 19:35:29 +04:00
|
|
|
|
Keymanager::setFileKey( $this->view, $relPath, $this->userId, $recrypted['key'] );
|
2013-01-24 22:37:34 +04:00
|
|
|
|
|
|
|
|
|
// Overwrite the existing file with the encrypted one
|
2013-02-05 19:35:29 +04:00
|
|
|
|
$this->view->file_put_contents( $legacyFile['path'], $recrypted['data'] );
|
2013-01-31 23:40:51 +04:00
|
|
|
|
|
|
|
|
|
$size = strlen( $recrypted['data'] );
|
|
|
|
|
|
|
|
|
|
// Add the file to the cache
|
2013-02-05 19:35:29 +04:00
|
|
|
|
\OC\Files\Filesystem::putFileInfo( $legacyFile['path'], array( 'encrypted'=>true, 'size' => $size ), '' );
|
2013-01-24 22:37:34 +04:00
|
|
|
|
|
|
|
|
|
}
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
|
|
|
|
}
|
2013-01-29 23:54:40 +04:00
|
|
|
|
|
|
|
|
|
\OC_FileProxy::$enabled = true;
|
|
|
|
|
|
|
|
|
|
// If files were found, return true
|
|
|
|
|
return true;
|
2013-01-23 23:24:26 +04:00
|
|
|
|
|
2013-01-29 23:54:40 +04:00
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// If no files were found, return false
|
|
|
|
|
return false;
|
|
|
|
|
|
2012-07-31 22:28:11 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-06 18:30:40 +04:00
|
|
|
|
/**
|
|
|
|
|
* @brief Return important encryption related paths
|
|
|
|
|
* @param string $pathName Name of the directory to return the path of
|
|
|
|
|
* @return string path
|
|
|
|
|
*/
|
2012-11-16 22:31:37 +04:00
|
|
|
|
public function getPath( $pathName ) {
|
|
|
|
|
|
|
|
|
|
switch ( $pathName ) {
|
|
|
|
|
|
|
|
|
|
case 'publicKeyDir':
|
|
|
|
|
|
|
|
|
|
return $this->publicKeyDir;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'encryptionDir':
|
|
|
|
|
|
|
|
|
|
return $this->encryptionDir;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'keyfilesPath':
|
|
|
|
|
|
|
|
|
|
return $this->keyfilesPath;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'publicKeyPath':
|
|
|
|
|
|
|
|
|
|
return $this->publicKeyPath;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'privateKeyPath':
|
|
|
|
|
|
|
|
|
|
return $this->privateKeyPath;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2013-02-12 19:48:04 +04:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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);
|
|
|
|
|
}
|
2013-02-19 23:16:50 +04:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Filter an array of UIDs to return only ones ready for sharing
|
|
|
|
|
* @param array $unfilteredUsers users to be checked for sharing readiness
|
|
|
|
|
* @return array $userIds filtered users
|
|
|
|
|
*/
|
|
|
|
|
public function filterShareReadyUsers( $unfilteredUsers ) {
|
|
|
|
|
|
|
|
|
|
// This array will collect the filtered IDs
|
|
|
|
|
$userIds = array();
|
|
|
|
|
|
|
|
|
|
// Loop through users and create array of UIDs that need new keyfiles
|
|
|
|
|
foreach ( $unfilteredUsers as $user ) {
|
|
|
|
|
|
|
|
|
|
$util = new Util( $this->view, $user );
|
|
|
|
|
|
|
|
|
|
// Check that the user is encryption capable, or is the
|
|
|
|
|
// public system user 'ownCloud' (for public shares)
|
|
|
|
|
if (
|
|
|
|
|
$util->ready()
|
|
|
|
|
or $user == 'ownCloud'
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
// 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', '"'.$user.'" is not setup for encryption', \OC_Log::WARN );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $userIds;
|
|
|
|
|
|
|
|
|
|
}
|
2012-07-11 20:51:27 +04:00
|
|
|
|
|
|
|
|
|
}
|