/** * restore encryption keys from trash bin * * @param \OC\Files\View $view * @param string $file complete path to file * @param string $filename name of file * @param string $uniqueFilename new file name to restore the file without overwriting existing files * @param string $location location of file * @param int $timestamp deleteion time * */ private static function restoreEncryptionKeys($view, $file, $filename, $uniqueFilename, $location, $timestamp) { // Take care of encryption keys TODO! Get '.key' in file between file name and delete date (also for permanent delete!) if (\OCP\App::isEnabled('files_encryption')) { $user = \OCP\User::getUser(); $rootView = new \OC\Files\View('/'); $target = \OC\Files\Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename); list($owner, $ownerPath) = self::getUidAndFilename($target); $util = new \OCA\Encryption\Util(new \OC\Files\View('/'), $user); if ($util->isSystemWideMountPoint($ownerPath)) { $baseDir = '/files_encryption/'; } else { $baseDir = $owner . '/files_encryption/'; } $path_parts = pathinfo($file); $source_location = $path_parts['dirname']; if ($view->is_dir('/files_trashbin/keyfiles/' . $file)) { if ($source_location != '.') { $keyfile = \OC\Files\Filesystem::normalizePath($user . '/files_trashbin/keyfiles/' . $source_location . '/' . $filename); $sharekey = \OC\Files\Filesystem::normalizePath($user . '/files_trashbin/share-keys/' . $source_location . '/' . $filename); } else { $keyfile = \OC\Files\Filesystem::normalizePath($user . '/files_trashbin/keyfiles/' . $filename); $sharekey = \OC\Files\Filesystem::normalizePath($user . '/files_trashbin/share-keys/' . $filename); } } else { $keyfile = \OC\Files\Filesystem::normalizePath($user . '/files_trashbin/keyfiles/' . $source_location . '/' . $filename . '.key'); } if ($timestamp) { $keyfile .= '.d' . $timestamp; } // disable proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ($rootView->file_exists($keyfile)) { // handle directory if ($rootView->is_dir($keyfile)) { // handle keyfiles $rootView->rename($keyfile, $baseDir . '/keyfiles/' . $ownerPath); // handle share-keys if ($timestamp) { $sharekey .= '.d' . $timestamp; } $rootView->rename($sharekey, $baseDir . '/share-keys/' . $ownerPath); } else { // handle keyfiles $rootView->rename($keyfile, $baseDir . '/keyfiles/' . $ownerPath . '.key'); // handle share-keys $ownerShareKey = \OC\Files\Filesystem::normalizePath($user . '/files_trashbin/share-keys/' . $source_location . '/' . $filename . '.' . $user . '.shareKey'); if ($timestamp) { $ownerShareKey .= '.d' . $timestamp; } // move only owners key $rootView->rename($ownerShareKey, $baseDir . '/share-keys/' . $ownerPath . '.' . $user . '.shareKey'); // try to re-share if file is shared $filesystemView = new \OC\Files\View('/'); $session = new \OCA\Encryption\Session($filesystemView); $util = new \OCA\Encryption\Util($filesystemView, $user); // fix the file size $absolutePath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files/' . $ownerPath); $util->fixFileSize($absolutePath); // get current sharing state $sharingEnabled = \OCP\Share::isEnabled(); // get users sharing this file $usersSharing = $util->getSharingUsersArray($sharingEnabled, $target); // Attempt to set shareKey $util->setSharedFileKeyfiles($session, $usersSharing, $target); } } // enable proxy \OC_FileProxy::$enabled = $proxyStatus; } }
/** * @param $path */ public function handleFile($path) { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); $session = new \OCA\Encryption\Session($view); $userId = Helper::getUser($path); $util = new Util($view, $userId); // split the path parts $pathParts = explode('/', $path); // get relative path $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); // only if file is on 'files' folder fix file size and sharing if (isset($pathParts[2]) && $pathParts[2] === 'files' && $util->fixFileSize($path)) { // get sharing app state $sharingEnabled = \OCP\Share::isEnabled(); // get users $usersSharing = $util->getSharingUsersArray($sharingEnabled, $relativePath); // update sharing-keys $util->setSharedFileKeyfiles($session, $usersSharing, $relativePath); } \OC_FileProxy::$enabled = $proxyStatus; }
/** * @return bool */ public function stream_close() { $this->flush(); // if there is no valid private key return false if ($this->privateKey === false) { // cleanup if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb' && !$this->isLocalTmpFile) { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ($this->rootView->file_exists($this->rawPath) && $this->size === 0) { fclose($this->handle); $this->rootView->unlink($this->rawPath); } // Re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; } // if private key is not valid redirect user to a error page Helper::redirectToErrorPage($this->session); } if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb' && $this->isLocalTmpFile === false && $this->size > 0 && $this->unencryptedSize > 0) { // only write keyfiles if it was a new file if ($this->newFile === true) { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; // Fetch user's public key $this->publicKey = Keymanager::getPublicKey($this->rootView, $this->keyId); // Check if OC sharing api is enabled $sharingEnabled = \OCP\Share::isEnabled(); // Get all users sharing the file includes current user $uniqueUserIds = $this->util->getSharingUsersArray($sharingEnabled, $this->relPath); $checkedUserIds = $this->util->filterShareReadyUsers($uniqueUserIds); // Fetch public keys for all sharing users $publicKeys = Keymanager::getPublicKeys($this->rootView, $checkedUserIds['ready']); // Encrypt enc key for all sharing users $this->encKeyfiles = Crypt::multiKeyEncrypt($this->plainKey, $publicKeys); // Save the new encrypted file key Keymanager::setFileKey($this->rootView, $this->util, $this->relPath, $this->encKeyfiles['data']); // Save the sharekeys Keymanager::setShareKeys($this->rootView, $this->util, $this->relPath, $this->encKeyfiles['keys']); // Re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; } // we need to update the file info for the real file, not for the // part file. $path = Helper::stripPartialFileExtension($this->rawPath); $fileInfo = array('mimetype' => $this->rootView->getMimeType($this->rawPath), 'encrypted' => true, 'unencrypted_size' => $this->unencryptedSize); // if we write a part file we also store the unencrypted size for // the part file so that it can be re-used later $this->rootView->putFileInfo($this->rawPath, $fileInfo); if ($path !== $this->rawPath) { $this->rootView->putFileInfo($path, $fileInfo); } } $result = fclose($this->handle); if ($result === false) { \OCP\Util::writeLog('Encryption library', 'Could not close stream, file could be corrupted', \OCP\Util::FATAL); } return $result; }
/** * decrypt given file with recovery key and encrypt it again to the owner and his new key * @param string $file * @param string $privateKey recovery key to decrypt the file */ private function recoverFile($file, $privateKey) { $sharingEnabled = \OCP\Share::isEnabled(); // Find out who, if anyone, is sharing the file if ($sharingEnabled) { $result = \OCP\Share::getUsersSharingFile($file, $this->userId, true); $userIds = $result['users']; $userIds[] = $this->recoveryKeyId; if ($result['public']) { $userIds[] = $this->publicShareKeyId; } } else { $userIds = array($this->userId, $this->recoveryKeyId); } $filteredUids = $this->filterShareReadyUsers($userIds); $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; //decrypt file key $encKeyfile = $this->view->file_get_contents($this->keyfilesPath . $file . ".key"); $shareKey = $this->view->file_get_contents($this->shareKeysPath . $file . "." . $this->recoveryKeyId . ".shareKey"); $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); // encrypt file key again to all users, this time with the new public key for the recovered use $userPubKeys = Keymanager::getPublicKeys($this->view, $filteredUids['ready']); $multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys); // write new keys to filesystem TDOO! $this->view->file_put_contents($this->keyfilesPath . $file . '.key', $multiEncKey['data']); foreach ($multiEncKey['keys'] as $userId => $shareKey) { $shareKeyPath = $this->shareKeysPath . $file . '.' . $userId . '.shareKey'; $this->view->file_put_contents($shareKeyPath, $shareKey); } // Return proxy to original status \OC_FileProxy::$enabled = $proxyStatus; }
/** * find all share keys for a given file * * @param string $filePath path to the file name relative to the user's files dir * for example "subdir/filename.txt" * @param string $shareKeyPath share key prefix path relative to the user's data dir * for example "user1/files_encryption/share-keys/subdir/filename.txt" * @param \OC\Files\View $rootView root view, relative to data/ * @return array list of share key files, path relative to data/$user */ public static function findShareKeys($filePath, $shareKeyPath, \OC\Files\View $rootView) { $result = array(); $user = \OCP\User::getUser(); $util = new Util($rootView, $user); // get current sharing state $sharingEnabled = \OCP\Share::isEnabled(); // get users sharing this file $usersSharing = $util->getSharingUsersArray($sharingEnabled, $filePath); $pathinfo = pathinfo($shareKeyPath); $baseDir = $pathinfo['dirname'] . '/'; $fileName = $pathinfo['basename']; foreach ($usersSharing as $user) { $keyName = $fileName . '.' . $user . '.shareKey'; if ($rootView->file_exists($baseDir . $keyName)) { $result[] = $baseDir . $keyName; } else { \OC_Log::write('Encryption library', 'No share key found for user "' . $user . '" for file "' . $fileName . '"', \OC_Log::WARN); } } return $result; }
/** * @param $fid * @param $uid * @param $wUid * @return bool|string * @throws \Exception * @throws \OC\HintException */ public function shareFile($uid, $wUid, $fid, $permission = 1) { $isEnabled = \OCP\Share::isEnabled(); $isAllowed = \OCP\Share::isResharingAllowed(); $sharedWith = \OCP\Share::getUsersItemShared('file', $fid, $uid, false, true); //$file = $this->connect->files()->getInfoById($fid); if ($isEnabled && $isAllowed && !in_array($wUid, $sharedWith)) { // \OCP\Constants::PERMISSION_READ // \OCP\Constants::PERMISSION_ALL // \OCP\Share::SHARE_TYPE_LINK // \OCP\Share::SHARE_TYPE_USER, $shareIsSuccess = \OC\Share\Share::shareItem('file', $fid, \OCP\Share::SHARE_TYPE_USER, $wUid, $permission); if ($shareIsSuccess) { $this->connect->update('*PREFIX*share', ['uid_initiator' => $uid], 'share_with = :share_with AND uid_owner = :uid_owner AND file_source = :file_source', [':share_with' => $wUid, ':uid_owner' => $uid, ':file_source' => $fid]); $token = \OC\Share\Share::shareItem('file', $fid, \OCP\Share::SHARE_TYPE_LINK, $wUid, $permission); $this->connect->update('*PREFIX*share', ['uid_initiator' => $uid, 'share_with' => null], 'uid_owner = :uid_owner AND file_source = :file_source AND token = :token', [':uid_owner' => $uid, ':file_source' => $fid, ':token' => $token]); return $token; } } }
/** * @param IAppContainer $c */ public function registerBackends(IAppContainer $c) { $l10n = $c->getServer()->getL10N($c->getAppName()); // Local backend: Default database backend $this->backends->queue(function () use($c, $l10n) { return $this->backendFactory->createBackend('org.ownCloud.local', $this->backends, function () use($l10n) { return new Calendar\Backend\Local\Backend($l10n); }, function (Calendar\IBackend $backend) use($c) { $db = $c->getServer()->getDatabaseConnection(); $factory = $c->query('CalendarFactory'); return new Calendar\Backend\Local\Calendar($db, $backend, $factory); }, function (Calendar\ICalendar $calendar) use($c) { $db = $c->getServer()->getDatabaseConnection(); $factory = $c->query('ObjectFactory'); return new Calendar\Backend\Local\Object($db, $calendar, $factory); }); }); // Contacts backend: show contact's birthdays and anniversaries $contactsManager = $c->getServer()->getContactsManager(); $this->backends->queue(function () use($c, $l10n, $contactsManager) { return $this->backendFactory->createBackend('org.ownCloud.contact', $this->backends, function () use($c, $contactsManager) { $appManager = $c->getServer()->getAppManager(); return new Calendar\Backend\Contact\Backend($contactsManager, $appManager); }, function (Calendar\IBackend $backend) use($c, $contactsManager) { $l10n = $c->getServer()->getL10N('calendar'); $calendarFactory = $c->query('CalendarFactory'); return new Calendar\Backend\Contact\Calendar($contactsManager, $backend, $l10n, $calendarFactory); }, function (Calendar\ICalendar $calendar) use($c, $contactsManager) { $l10n = $c->getServer()->getL10N('calendar'); $objectFactory = $c->query('ObjectFactory'); return new Calendar\Backend\Contact\Object($contactsManager, $calendar, $l10n, $objectFactory); }); }); // Sharing backend: Enabling users to share calendars if (Share::isEnabled() && false) { $this->backends->queue(function () use($c, $l10n) { return $this->backendFactory->createBackend('org.ownCloud.sharing', $this->backends, function () { return new Calendar\Backend\Sharing\Backend(); }, function (Calendar\IBackend $backend) { return new Calendar\Backend\Sharing\Calendar($backend); }, function (Calendar\ICalendar $calendar) { return new Calendar\Backend\Sharing\Object($calendar); }); }); } // Webcal Backend: Show ICS files on the net if (function_exists('curl_init')) { $this->backends->queue(function () use($c, $l10n) { return $this->backendFactory->createBackend('org.ownCloud.webcal', $this->backends, function () use($c, $l10n) { $subscriptions = $c->query('SubscriptionBusinessLayer'); $cacheFactory = $c->getServer()->getMemCacheFactory(); return new Calendar\Backend\WebCal\Backend($subscriptions, $l10n, $cacheFactory); }, function (Calendar\IBackend $backend) use($c, $l10n) { $subscriptions = $c->query('SubscriptionBusinessLayer'); $cacheFactory = $c->getServer()->getMemCacheFactory(); $calendarFactory = $c->query('CalendarFactory'); return new Calendar\Backend\WebCal\Calendar($subscriptions, $l10n, $cacheFactory, $backend, $calendarFactory); }, function (Calendar\ICalendar $calendar) use($c, $l10n) { $subscriptions = $c->query('SubscriptionBusinessLayer'); $cacheFactory = $c->getServer()->getMemCacheFactory(); $objectFactory = $c->query('ObjectFactory'); return new Calendar\Backend\WebCal\Object($subscriptions, $l10n, $cacheFactory, $calendar, $objectFactory); }); }); } }
/** * @return bool */ public function stream_close() { $this->flush(); // if there is no valid private key return false if ($this->privateKey === false) { // cleanup if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb') { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ($this->rootView->file_exists($this->rawPath) && $this->size === 0) { $this->rootView->unlink($this->rawPath); } // Re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; } // if private key is not valid redirect user to a error page \OCA\Encryption\Helper::redirectToErrorPage(); } if ($this->meta['mode'] !== 'r' and $this->meta['mode'] !== 'rb' and $this->size > 0) { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; // Fetch user's public key $this->publicKey = Keymanager::getPublicKey($this->rootView, $this->userId); // Check if OC sharing api is enabled $sharingEnabled = \OCP\Share::isEnabled(); $util = new Util($this->rootView, $this->userId); // Get all users sharing the file includes current user $uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath, $this->userId); // Fetch public keys for all sharing users $publicKeys = Keymanager::getPublicKeys($this->rootView, $uniqueUserIds); // Encrypt enc key for all sharing users $this->encKeyfiles = Crypt::multiKeyEncrypt($this->plainKey, $publicKeys); // Save the new encrypted file key Keymanager::setFileKey($this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data']); // Save the sharekeys Keymanager::setShareKeys($this->rootView, $this->relPath, $this->encKeyfiles['keys']); // get file info $fileInfo = $this->rootView->getFileInfo($this->rawPath); if (!is_array($fileInfo)) { $fileInfo = array(); } // Re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; // set encryption data $fileInfo['encrypted'] = true; $fileInfo['size'] = $this->size; $fileInfo['unencrypted_size'] = $this->unencryptedSize; // set fileinfo $this->rootView->putFileInfo($this->rawPath, $fileInfo); } return fclose($this->handle); }
/** * {@inheritDoc} */ public function canBeEnabled() { return Share::isEnabled(); }
/** * after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing * @param array $params array with oldpath and newpath * * This function is connected to the rename signal of OC_Filesystem and adjust the name and location * of the stored versions along the actual file */ public static function postRename($params) { if (\OCP\App::isEnabled('files_encryption') === false) { return true; } // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC\Files\View('/'); $session = new \OCA\Encryption\Session($view); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); if (isset(self::$renamedFiles[$params['oldpath']]['uid']) && isset(self::$renamedFiles[$params['oldpath']]['path'])) { $ownerOld = self::$renamedFiles[$params['oldpath']]['uid']; $pathOld = self::$renamedFiles[$params['oldpath']]['path']; } else { \OCP\Util::writeLog('Encryption library', "can't get path and owner from the file before it was renamed", \OCP\Util::DEBUG); return false; } list($ownerNew, $pathNew) = $util->getUidAndFilename($params['newpath']); // Format paths to be relative to user files dir if ($util->isSystemWideMountPoint($pathOld)) { $oldKeyfilePath = 'files_encryption/keyfiles/' . $pathOld; $oldShareKeyPath = 'files_encryption/share-keys/' . $pathOld; } else { $oldKeyfilePath = $ownerOld . '/' . 'files_encryption/keyfiles/' . $pathOld; $oldShareKeyPath = $ownerOld . '/' . 'files_encryption/share-keys/' . $pathOld; } if ($util->isSystemWideMountPoint($pathNew)) { $newKeyfilePath = 'files_encryption/keyfiles/' . $pathNew; $newShareKeyPath = 'files_encryption/share-keys/' . $pathNew; } else { $newKeyfilePath = $ownerNew . '/files_encryption/keyfiles/' . $pathNew; $newShareKeyPath = $ownerNew . '/files_encryption/share-keys/' . $pathNew; } // create new key folders if it doesn't exists if (!$view->file_exists(dirname($newShareKeyPath))) { $view->mkdir(dirname($newShareKeyPath)); } if (!$view->file_exists(dirname($newKeyfilePath))) { $view->mkdir(dirname($newKeyfilePath)); } // handle share keys if (!$view->is_dir($oldKeyfilePath)) { $oldKeyfilePath .= '.key'; $newKeyfilePath .= '.key'; // handle share-keys $matches = Helper::findShareKeys($oldShareKeyPath, $view); foreach ($matches as $src) { $dst = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $src)); $view->rename($src, $dst); } } else { // handle share-keys folders $view->rename($oldShareKeyPath, $newShareKeyPath); } // Rename keyfile so it isn't orphaned if ($view->file_exists($oldKeyfilePath)) { $view->rename($oldKeyfilePath, $newKeyfilePath); } // update share keys $sharingEnabled = \OCP\Share::isEnabled(); // get users $usersSharing = $util->getSharingUsersArray($sharingEnabled, $pathNew); // update sharing-keys $util->setSharedFileKeyfiles($session, $usersSharing, $pathNew); \OC_FileProxy::$enabled = $proxyStatus; }
/** * update keyfiles and share keys recursively * * @param string $path to the file/folder */ private static function updateKeyfiles($path) { $view = new \OC\Files\View('/'); $userId = \OCP\User::getUser(); $session = new Session($view); $util = new Util($view, $userId); $sharingEnabled = \OCP\Share::isEnabled(); $mountManager = \OC\Files\Filesystem::getMountManager(); $mount = $mountManager->find('/' . $userId . '/files' . $path); $mountPoint = $mount->getMountPoint(); // if a folder was shared, get a list of all (sub-)folders if ($view->is_dir('/' . $userId . '/files' . $path)) { $allFiles = $util->getAllFiles($path, $mountPoint); } else { $allFiles = array($path); } foreach ($allFiles as $path) { $usersSharing = $util->getSharingUsersArray($sharingEnabled, $path); $util->setSharedFileKeyfiles($session, $usersSharing, $path); } }
/** * @brief delete all share keys of a given file * @param \OC_FilesystemView $view * @param string $userId owner of the file * @param string $filePath path to the file, relative to the owners file dir */ public static function delAllShareKeys($view, $userId, $filePath) { $filePath = ltrim($filePath, '/'); if ($view->file_exists('/' . $userId . '/files/' . $filePath)) { \OCP\Util::writeLog('Encryption library', 'File still exists, stop deleting share keys!', \OCP\Util::ERROR); return false; } if ($filePath === '') { \OCP\Util::writeLog('Encryption library', 'Can\'t delete share-keys empty path given!', \OCP\Util::ERROR); return false; } $util = new util($view, $userId); if ($util->isSystemWideMountPoint($filePath)) { $baseDir = '/files_encryption/share-keys/'; } else { $baseDir = $userId . '/files_encryption/share-keys/'; } $result = true; if ($view->is_dir($baseDir . $filePath)) { \OCP\Util::writeLog('files_encryption', 'delAllShareKeys: delete share keys: ' . $baseDir . $filePath, \OCP\Util::DEBUG); $result = $view->unlink($baseDir . $filePath); } else { $sharingEnabled = \OCP\Share::isEnabled(); $users = $util->getSharingUsersArray($sharingEnabled, $filePath); foreach ($users as $user) { $keyName = $baseDir . $filePath . '.' . $user . '.shareKey'; if ($view->file_exists($keyName)) { \OCP\Util::writeLog('files_encryption', 'dellAllShareKeys: delete share keys: "' . $keyName . '"', \OCP\Util::DEBUG); $result &= $view->unlink($keyName); } } } return (bool) $result; }
private function shareFileToUsers(\OC\Files\FileInfo $file, array $uids) { $user = $this->configurator->get('collab_user'); $result = []; $owner = $user; $shareType = $file['mimetype'] == 2 ? 'folder' : 'file'; $sharedWith = \OCP\Share::getUsersItemShared($shareType, $file['fileid'], $owner, false, true); $isEnabled = \OCP\Share::isEnabled(); $isAllowed = \OCP\Share::isResharingAllowed(); if ($isEnabled && $isAllowed) { $sharedUsers = is_array($sharedWith) ? array_values($sharedWith) : []; foreach ($uids as $uid) { if ($owner == $uid || in_array($uid, $sharedUsers)) { continue; } // \OCP\Share::SHARE_TYPE_USER // \OCP\Constants::PERMISSION_ALL //$resultToken = \OCP\Share::shareItem($shareType, $file['fileid'], 0, $uid, 31); $resultToken = $this->connect->files()->shareFile($owner, $uid, $file['fileid'], \OCP\Constants::PERMISSION_ALL); $result[$uid] = ['uid' => $uid, 'file' => $file['path'], 'file_token' => $resultToken]; } } return $result; }
/** * update keyfiles and share keys recursively * * @param string $path to the file/folder * @param string $type 'file' or 'folder' */ private static function updateKeyfiles($path, $type) { $view = new \OC_FilesystemView('/'); $session = new \OCA\Encryption\Session($view); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); $sharingEnabled = \OCP\Share::isEnabled(); // if a folder was shared, get a list of all (sub-)folders if ($type === 'folder') { $allFiles = $util->getAllFiles($path); } else { $allFiles = array($path); } foreach ($allFiles as $path) { $usersSharing = $util->getSharingUsersArray($sharingEnabled, $path); $util->setSharedFileKeyfiles($session, $usersSharing, $path); } }
/** * @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing * @param array with oldpath and newpath * * This function is connected to the rename signal of OC_Filesystem and adjust the name and location * of the stored versions along the actual file */ public static function postRename($params) { if (\OCP\App::isEnabled('files_encryption') === false) { return true; } // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); $session = new \OCA\Encryption\Session($view); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); // Format paths to be relative to user files dir if ($util->isSystemWideMountPoint($params['oldpath'])) { $baseDir = 'files_encryption/'; $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath']; } else { $baseDir = $userId . '/' . 'files_encryption/'; $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath']; } if ($util->isSystemWideMountPoint($params['newpath'])) { $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath']; } else { $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath']; } // add key ext if this is not an folder if (!$view->is_dir($oldKeyfilePath)) { $oldKeyfilePath .= '.key'; $newKeyfilePath .= '.key'; // handle share-keys $localKeyPath = $view->getLocalFile($baseDir . 'share-keys/' . $params['oldpath']); $escapedPath = Helper::escapeGlobPattern($localKeyPath); $matches = glob($escapedPath . '*.shareKey'); foreach ($matches as $src) { $dst = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src)); // create destination folder if not exists if (!file_exists(dirname($dst))) { mkdir(dirname($dst), 0750, true); } rename($src, $dst); } } else { // handle share-keys folders $oldShareKeyfilePath = $baseDir . 'share-keys/' . $params['oldpath']; $newShareKeyfilePath = $baseDir . 'share-keys/' . $params['newpath']; // create destination folder if not exists if (!$view->file_exists(dirname($newShareKeyfilePath))) { $view->mkdir(dirname($newShareKeyfilePath), 0750, true); } $view->rename($oldShareKeyfilePath, $newShareKeyfilePath); } // Rename keyfile so it isn't orphaned if ($view->file_exists($oldKeyfilePath)) { // create destination folder if not exists if (!$view->file_exists(dirname($newKeyfilePath))) { $view->mkdir(dirname($newKeyfilePath), 0750, true); } $view->rename($oldKeyfilePath, $newKeyfilePath); } // build the path to the file $newPath = '/' . $userId . '/files' . $params['newpath']; $newPathRelative = $params['newpath']; if ($util->fixFileSize($newPath)) { // get sharing app state $sharingEnabled = \OCP\Share::isEnabled(); // get users $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative); // update sharing-keys $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative); } \OC_FileProxy::$enabled = $proxyStatus; }
/** * decrypt given file with recovery key and encrypt it again to the owner and his new key * @param string $file * @param string $privateKey recovery key to decrypt the file */ private function recoverFile($file, $privateKey) { $sharingEnabled = \OCP\Share::isEnabled(); // Find out who, if anyone, is sharing the file if ($sharingEnabled) { $result = \OCP\Share::getUsersSharingFile($file, $this->userId, true); $userIds = $result['users']; $userIds[] = $this->recoveryKeyId; if ($result['public']) { $userIds[] = $this->publicShareKeyId; } } else { $userIds = array($this->userId, $this->recoveryKeyId); } $filteredUids = $this->filterShareReadyUsers($userIds); //decrypt file key $encKeyfile = Keymanager::getFileKey($this->view, $this, $file); $shareKey = Keymanager::getShareKey($this->view, $this->recoveryKeyId, $this, $file); $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); // encrypt file key again to all users, this time with the new public key for the recovered use $userPubKeys = Keymanager::getPublicKeys($this->view, $filteredUids['ready']); $multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys); Keymanager::setFileKey($this->view, $this, $file, $multiEncKey['data']); Keymanager::setShareKeys($this->view, $this, $file, $multiEncKey['keys']); }
/** * Share selected files with selected users */ public function shareFiles() { $this->prepareUsersForShare(); $files = array(); foreach ($this->files as $id) { $file = $this->Files->getById($id)[0]; $fileOwner = \OC\Files\Filesystem::getOwner($file['path']); $sharetype = $file['mimetype'] == 2 ? 'folder' : 'file'; $sharedWith = \OCP\Share::getUsersItemShared($sharetype, $file['fileid'], $fileOwner, false, true); $isenabled = \OCP\Share::isEnabled(); $isallowed = \OCP\Share::isResharingAllowed(); foreach ($this->subscriberToShare as $userid) { if (isset($file['fileid']) && is_array($file) && !in_array($userid, $sharedWith) && !($userid == $this->author) && ($fileOwner == $this->author || $file['permissions'] >= 16) && $isenabled && $isallowed) { //try { \OCP\Share::shareItem($sharetype, $file['fileid'], \OCP\Share::SHARE_TYPE_USER, $userid, 1); $files[] = $file['fileid']; //} //catch (\Exception $e) { // echo $e->getMessage(); //} } } } $this->forSaveData['attachements'] = $files; $this->fileLinks = Helper::makeAttachLinks($files, $this->Files); //print_r($this->fileLinks); //file_put_contents('/tmp/inb.log', "\n\nfileLinks : "print_r($this->fileLinks, true)."\n", FILE_APPEND); /* foreach ($_POST['select-files'] as $id => $on) { if ($on == 'on') { $file = $files->getById($id)[0]; $fileOwner = \OC\Files\Filesystem::getOwner($file['path']); $sharetype = $file['mimetype'] == 2 ? 'folder' : 'file'; $sharedWith = \OCP\Share::getUsersItemShared($sharetype, $file['fileid'], $fileOwner, false, true); foreach ($allusers as $userid => $user) { if (isset($file['fileid']) && is_array($file) && isset($file['fileid']) && !in_array($userid, $sharedWith) && !($userid == $this->userId)) { //Helper::shareFile($file['name'], $user, $userid); \OCP\Share::shareItem($sharetype, $file['fileid'], \OCP\Share::SHARE_TYPE_USER, $userid, 1); $filesid[] = $id; } } } } */ }