2013-05-09 17:36:18 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ownCloud
|
|
|
|
*
|
|
|
|
* @author Florin Peter
|
|
|
|
* @copyright 2013 Florin Peter <owncloud@florin-peter.de>
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace OCA\Encryption;
|
|
|
|
|
2013-05-16 22:58:41 +00:00
|
|
|
/**
|
2013-05-27 18:44:38 +00:00
|
|
|
* @brief Class to manage registration of hooks an various helper methods
|
2013-05-16 22:58:41 +00:00
|
|
|
* @package OCA\Encryption
|
|
|
|
*/
|
2013-05-27 15:26:58 +00:00
|
|
|
class Helper {
|
2013-05-19 23:24:36 +00:00
|
|
|
|
2013-05-09 17:36:18 +00:00
|
|
|
/**
|
|
|
|
* @brief register share related hooks
|
2013-05-19 23:24:36 +00:00
|
|
|
*
|
|
|
|
*/
|
2013-05-23 21:56:31 +00:00
|
|
|
public static function registerShareHooks() {
|
2013-05-19 23:24:36 +00:00
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
\OCP\Util::connectHook('OCP\Share', 'pre_shared', 'OCA\Encryption\Hooks', 'preShared');
|
|
|
|
\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared');
|
|
|
|
\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare');
|
2013-05-19 23:24:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief register user related hooks
|
|
|
|
*
|
2013-05-09 17:36:18 +00:00
|
|
|
*/
|
2013-05-23 21:56:31 +00:00
|
|
|
public static function registerUserHooks() {
|
2013-05-09 17:36:18 +00:00
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
\OCP\Util::connectHook('OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login');
|
|
|
|
\OCP\Util::connectHook('OC_User', 'post_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase');
|
2013-06-06 11:32:02 +00:00
|
|
|
\OCP\Util::connectHook('OC_User', 'pre_setPassword', 'OCA\Encryption\Hooks', 'preSetPassphrase');
|
2013-05-27 15:26:58 +00:00
|
|
|
\OCP\Util::connectHook('OC_User', 'post_createUser', 'OCA\Encryption\Hooks', 'postCreateUser');
|
|
|
|
\OCP\Util::connectHook('OC_User', 'post_deleteUser', 'OCA\Encryption\Hooks', 'postDeleteUser');
|
2013-05-09 17:36:18 +00:00
|
|
|
}
|
|
|
|
|
2013-05-19 23:24:36 +00:00
|
|
|
/**
|
|
|
|
* @brief register filesystem related hooks
|
|
|
|
*
|
|
|
|
*/
|
2013-05-23 21:56:31 +00:00
|
|
|
public static function registerFilesystemHooks() {
|
2013-05-19 23:24:36 +00:00
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
|
2013-05-19 23:24:36 +00:00
|
|
|
}
|
|
|
|
|
2013-06-27 12:09:22 +00:00
|
|
|
/**
|
2013-06-27 12:14:25 +00:00
|
|
|
* @brief register app management related hooks
|
2013-06-27 12:09:22 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
public static function registerAppHooks() {
|
|
|
|
|
|
|
|
\OCP\Util::connectHook('OC_App', 'pre_disable', 'OCA\Encryption\Hooks', 'preDisable');
|
|
|
|
}
|
|
|
|
|
2013-05-19 23:24:36 +00:00
|
|
|
/**
|
|
|
|
* @brief setup user for files_encryption
|
|
|
|
*
|
|
|
|
* @param Util $util
|
|
|
|
* @param string $password
|
|
|
|
* @return bool
|
|
|
|
*/
|
2013-05-27 15:26:58 +00:00
|
|
|
public static function setupUser($util, $password) {
|
2013-05-19 23:24:36 +00:00
|
|
|
// Check files_encryption infrastructure is ready for action
|
2013-05-27 15:26:58 +00:00
|
|
|
if (!$util->ready()) {
|
2013-05-19 23:24:36 +00:00
|
|
|
|
2013-05-27 18:51:52 +00:00
|
|
|
\OCP\Util::writeLog('Encryption library', 'User account "' . $util->getUserId()
|
2013-06-03 16:42:13 +00:00
|
|
|
. '" is not ready for encryption; configuration started', \OCP\Util::DEBUG);
|
2013-05-19 23:24:36 +00:00
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
if (!$util->setupServerSide($password)) {
|
2013-05-19 23:24:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2013-05-16 22:58:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief enable recovery
|
|
|
|
*
|
|
|
|
* @param $recoveryKeyId
|
|
|
|
* @param $recoveryPassword
|
|
|
|
* @internal param \OCA\Encryption\Util $util
|
|
|
|
* @internal param string $password
|
|
|
|
* @return bool
|
|
|
|
*/
|
2013-05-27 15:26:58 +00:00
|
|
|
public static function adminEnableRecovery($recoveryKeyId, $recoveryPassword) {
|
2013-06-03 12:19:31 +00:00
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
$view = new \OC\Files\View('/');
|
2013-05-16 22:58:41 +00:00
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
if ($recoveryKeyId === null) {
|
|
|
|
$recoveryKeyId = 'recovery_' . substr(md5(time()), 0, 8);
|
|
|
|
\OC_Appconfig::setValue('files_encryption', 'recoveryKeyId', $recoveryKeyId);
|
2013-05-16 22:58:41 +00:00
|
|
|
}
|
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
if (!$view->is_dir('/owncloud_private_key')) {
|
|
|
|
$view->mkdir('/owncloud_private_key');
|
2013-05-16 22:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
2013-05-27 15:26:58 +00:00
|
|
|
(!$view->file_exists("/public-keys/" . $recoveryKeyId . ".public.key")
|
|
|
|
|| !$view->file_exists("/owncloud_private_key/" . $recoveryKeyId . ".private.key"))
|
2013-05-16 22:58:41 +00:00
|
|
|
) {
|
|
|
|
|
|
|
|
$keypair = \OCA\Encryption\Crypt::createKeypair();
|
|
|
|
|
|
|
|
\OC_FileProxy::$enabled = false;
|
|
|
|
|
|
|
|
// Save public key
|
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
if (!$view->is_dir('/public-keys')) {
|
|
|
|
$view->mkdir('/public-keys');
|
2013-05-16 22:58:41 +00:00
|
|
|
}
|
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
$view->file_put_contents('/public-keys/' . $recoveryKeyId . '.public.key', $keypair['publicKey']);
|
2013-05-16 22:58:41 +00:00
|
|
|
|
2013-07-01 19:12:21 +00:00
|
|
|
// Encrypt private key empty passphrase
|
2013-05-27 15:26:58 +00:00
|
|
|
$encryptedPrivateKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], $recoveryPassword);
|
2013-05-16 22:58:41 +00:00
|
|
|
|
|
|
|
// Save private key
|
2013-05-27 15:26:58 +00:00
|
|
|
$view->file_put_contents('/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey);
|
2013-05-16 22:58:41 +00:00
|
|
|
|
|
|
|
\OC_FileProxy::$enabled = true;
|
|
|
|
|
|
|
|
// Set recoveryAdmin as enabled
|
2013-05-27 15:26:58 +00:00
|
|
|
\OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1);
|
2013-05-16 22:58:41 +00:00
|
|
|
|
|
|
|
$return = true;
|
|
|
|
|
|
|
|
} else { // get recovery key and check the password
|
2013-05-27 15:26:58 +00:00
|
|
|
$util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser());
|
|
|
|
$return = $util->checkRecoveryPassword($recoveryPassword);
|
|
|
|
if ($return) {
|
|
|
|
\OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1);
|
2013-05-16 22:58:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief disable recovery
|
|
|
|
*
|
|
|
|
* @param $recoveryPassword
|
|
|
|
* @return bool
|
|
|
|
*/
|
2013-05-27 15:26:58 +00:00
|
|
|
public static function adminDisableRecovery($recoveryPassword) {
|
|
|
|
$util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser());
|
|
|
|
$return = $util->checkRecoveryPassword($recoveryPassword);
|
2013-05-16 22:58:41 +00:00
|
|
|
|
2013-05-27 15:26:58 +00:00
|
|
|
if ($return) {
|
2013-05-16 22:58:41 +00:00
|
|
|
// Set recoveryAdmin as disabled
|
2013-05-27 15:26:58 +00:00
|
|
|
\OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 0);
|
2013-05-16 22:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $return;
|
|
|
|
}
|
2013-05-28 07:27:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief checks if access is public/anonymous user
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public static function isPublicAccess() {
|
|
|
|
if (\OCP\USER::getUser() === false
|
|
|
|
|| (isset($_GET['service']) && $_GET['service'] == 'files'
|
|
|
|
&& isset($_GET['t']))
|
|
|
|
) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-05-29 23:13:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Format a path to be relative to the /user/files/ directory
|
|
|
|
* @param string $path the absolute path
|
|
|
|
* @return string e.g. turns '/admin/files/test.txt' into 'test.txt'
|
|
|
|
*/
|
|
|
|
public static function stripUserFilesPath($path) {
|
|
|
|
$trimmed = ltrim($path, '/');
|
|
|
|
$split = explode('/', $trimmed);
|
2013-06-10 09:03:07 +00:00
|
|
|
|
|
|
|
// it is not a file relative to data/user/files
|
|
|
|
if ($split[1] !== 'files') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-05-29 23:13:22 +00:00
|
|
|
$sliced = array_slice($split, 2);
|
|
|
|
$relPath = implode('/', $sliced);
|
|
|
|
|
|
|
|
return $relPath;
|
|
|
|
}
|
2013-06-03 21:41:57 +00:00
|
|
|
|
2013-06-10 09:03:07 +00:00
|
|
|
/**
|
|
|
|
* @brief get path to the correspondig file in data/user/files
|
|
|
|
* @param string $path path to a version or a file in the trash
|
|
|
|
* @return string path to correspondig file relative to data/user/files
|
|
|
|
*/
|
|
|
|
public static function getPathToRealFile($path) {
|
|
|
|
$trimmed = ltrim($path, '/');
|
|
|
|
$split = explode('/', $trimmed);
|
|
|
|
|
|
|
|
if ($split[1] !== "files_versions") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$sliced = array_slice($split, 2);
|
|
|
|
$realPath = implode('/', $sliced);
|
|
|
|
//remove the last .v
|
|
|
|
$realPath = substr($realPath, 0, strrpos($realPath, '.v'));
|
|
|
|
|
|
|
|
return $realPath;
|
|
|
|
}
|
|
|
|
|
2013-06-03 21:41:57 +00:00
|
|
|
/**
|
|
|
|
* @brief redirect to a error page
|
|
|
|
*/
|
|
|
|
public static function redirectToErrorPage() {
|
|
|
|
$location = \OC_Helper::linkToAbsolute('apps/files_encryption/files', 'error.php');
|
2013-06-03 22:41:47 +00:00
|
|
|
$post = 0;
|
|
|
|
if(count($_POST) > 0) {
|
|
|
|
$post = 1;
|
|
|
|
}
|
|
|
|
header('Location: ' . $location . '?p=' . $post);
|
2013-06-03 21:41:57 +00:00
|
|
|
exit();
|
|
|
|
}
|
2013-07-01 10:16:36 +00:00
|
|
|
|
|
|
|
/**
|
2013-07-01 19:12:21 +00:00
|
|
|
* check requirements for encryption app.
|
2013-07-01 10:16:36 +00:00
|
|
|
* @return bool true if requirements are met
|
|
|
|
*/
|
|
|
|
public static function checkRequirements() {
|
|
|
|
$result = true;
|
|
|
|
|
|
|
|
//openssl extension needs to be loaded
|
|
|
|
$result &= extension_loaded("openssl");
|
|
|
|
// we need php >= 5.3.3
|
2013-07-01 10:23:26 +00:00
|
|
|
$result &= version_compare(phpversion(), '5.3.3', '>=');
|
2013-07-01 10:16:36 +00:00
|
|
|
|
2013-07-01 15:18:16 +00:00
|
|
|
return (bool) $result;
|
2013-07-01 10:16:36 +00:00
|
|
|
}
|
2013-07-05 12:58:33 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief glob uses different pattern than regular expressions, escape glob pattern only
|
|
|
|
* @param unescaped path
|
|
|
|
* @return escaped path
|
|
|
|
*/
|
|
|
|
public static function escapeGlobPattern($path) {
|
|
|
|
return preg_replace('/(\*|\?|\[)/', '[$1]', $path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|