summaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2015-08-24 12:10:15 +0200
committerMorris Jobke <hey@morrisjobke.de>2015-08-24 12:10:15 +0200
commitb3495a1dc9ca339e839a3fda169bf9ce8656484d (patch)
tree4bc396b37d231011474638cd93104c5feb51b350 /lib/private
parentcca35f0c3e94ce5270e3f2fa3619d08a976ab650 (diff)
parent6a3fb0d3b36dce7a6583d58ded1b133f086e2a95 (diff)
downloadnextcloud-server-b3495a1dc9ca339e839a3fda169bf9ce8656484d.tar.gz
nextcloud-server-b3495a1dc9ca339e839a3fda169bf9ce8656484d.zip
Merge pull request #18482 from owncloud/encrypt-session-data
Add a session wrapper to encrypt the data before storing it on disk
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/server.php41
-rw-r--r--lib/private/session/cryptosessiondata.php147
-rw-r--r--lib/private/session/cryptowrapper.php96
3 files changed, 283 insertions, 1 deletions
diff --git a/lib/private/server.php b/lib/private/server.php
index ff78536cec0..91ffe1b5e4c 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -40,6 +40,7 @@ use bantu\IniGetWrapper\IniGetWrapper;
use OC\AppFramework\Http\Request;
use OC\AppFramework\Db\Db;
use OC\AppFramework\Utility\SimpleContainer;
+use OC\AppFramework\Utility\TimeFactory;
use OC\Command\AsyncBus;
use OC\Diagnostics\EventLogger;
use OC\Diagnostics\NullEventLogger;
@@ -56,6 +57,7 @@ use OC\Security\Crypto;
use OC\Security\Hasher;
use OC\Security\SecureRandom;
use OC\Security\TrustedDomainHelper;
+use OC\Session\CryptoWrapper;
use OC\Tagging\TagMapper;
use OCP\IServerContainer;
use Symfony\Component\EventDispatcher\EventDispatcher;
@@ -159,7 +161,12 @@ class Server extends SimpleContainer implements IServerContainer {
});
$this->registerService('UserSession', function (Server $c) {
$manager = $c->getUserManager();
- $userSession = new \OC\User\Session($manager, new \OC\Session\Memory(''));
+
+ $session = new \OC\Session\Memory('');
+ $cryptoWrapper = $c->getSessionCryptoWrapper();
+ $session = $cryptoWrapper->wrapSession($session);
+
+ $userSession = new \OC\User\Session($manager, $session);
$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
\OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password));
});
@@ -462,6 +469,31 @@ class Server extends SimpleContainer implements IServerContainer {
$this->registerService('EventDispatcher', function() {
return new EventDispatcher();
});
+ $this->registerService('CryptoWrapper', function (Server $c) {
+ // FIXME: Instantiiated here due to cyclic dependency
+ $request = new Request(
+ [
+ 'get' => $_GET,
+ 'post' => $_POST,
+ 'files' => $_FILES,
+ 'server' => $_SERVER,
+ 'env' => $_ENV,
+ 'cookies' => $_COOKIE,
+ 'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
+ ? $_SERVER['REQUEST_METHOD']
+ : null,
+ ],
+ new SecureRandom(),
+ $c->getConfig()
+ );
+
+ return new CryptoWrapper(
+ $c->getConfig(),
+ $c->getCrypto(),
+ $c->getSecureRandom(),
+ $request
+ );
+ });
}
/**
@@ -977,4 +1009,11 @@ class Server extends SimpleContainer implements IServerContainer {
public function getEventDispatcher() {
return $this->query('EventDispatcher');
}
+
+ /**
+ * @return \OC\Session\CryptoWrapper
+ */
+ public function getSessionCryptoWrapper() {
+ return $this->query('CryptoWrapper');
+ }
}
diff --git a/lib/private/session/cryptosessiondata.php b/lib/private/session/cryptosessiondata.php
new file mode 100644
index 00000000000..60d22b25e97
--- /dev/null
+++ b/lib/private/session/cryptosessiondata.php
@@ -0,0 +1,147 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Session;
+
+use OCP\ISession;
+use OCP\Security\ICrypto;
+
+/**
+ * Class CryptoSessionData
+ *
+ * @package OC\Session
+ */
+class CryptoSessionData implements \ArrayAccess, ISession {
+ /** @var ISession */
+ protected $session;
+
+ /** @var \OCP\Security\ICrypto */
+ protected $crypto;
+
+ /** @var string */
+ protected $passphrase;
+
+ /**
+ * @param ISession $session
+ * @param ICrypto $crypto
+ * @param string $passphrase
+ */
+ public function __construct(ISession $session, ICrypto $crypto, $passphrase) {
+ $this->crypto = $crypto;
+ $this->session = $session;
+ $this->passphrase = $passphrase;
+ }
+
+ /**
+ * Set a value in the session
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function set($key, $value) {
+ $encryptedValue = $this->crypto->encrypt(json_encode($value), $this->passphrase);
+ $this->session->set($key, $encryptedValue);
+ }
+
+ /**
+ * Get a value from the session
+ *
+ * @param string $key
+ * @return string|null Either the value or null
+ */
+ public function get($key) {
+ $encryptedValue = $this->session->get($key);
+ if ($encryptedValue === null) {
+ return null;
+ }
+
+ try {
+ $value = $this->crypto->decrypt($encryptedValue, $this->passphrase);
+ return json_decode($value);
+ } catch (\Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * Check if a named key exists in the session
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function exists($key) {
+ return $this->session->exists($key);
+ }
+
+ /**
+ * Remove a $key/$value pair from the session
+ *
+ * @param string $key
+ */
+ public function remove($key) {
+ $this->session->remove($key);
+ }
+
+ /**
+ * Reset and recreate the session
+ */
+ public function clear() {
+ $this->session->clear();
+ }
+
+ /**
+ * Close the session and release the lock
+ */
+ public function close() {
+ $this->session->close();
+ }
+
+ /**
+ * @param mixed $offset
+ * @return bool
+ */
+ public function offsetExists($offset) {
+ return $this->exists($offset);
+ }
+
+ /**
+ * @param mixed $offset
+ * @return mixed
+ */
+ public function offsetGet($offset) {
+ return $this->get($offset);
+ }
+
+ /**
+ * @param mixed $offset
+ * @param mixed $value
+ */
+ public function offsetSet($offset, $value) {
+ $this->set($offset, $value);
+ }
+
+ /**
+ * @param mixed $offset
+ */
+ public function offsetUnset($offset) {
+ $this->remove($offset);
+ }
+}
diff --git a/lib/private/session/cryptowrapper.php b/lib/private/session/cryptowrapper.php
new file mode 100644
index 00000000000..62bdcbfb719
--- /dev/null
+++ b/lib/private/session/cryptowrapper.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Session;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\ISession;
+use OCP\Security\ICrypto;
+use OCP\Security\ISecureRandom;
+
+/**
+ * Class CryptoWrapper provides some rough basic level of additional security by
+ * storing the session data in an encrypted form.
+ *
+ * The content of the session is encrypted using another cookie sent by the browser.
+ * One should note that an adversary with access to the source code or the system
+ * memory is still able to read the original session ID from the users' request.
+ * This thus can not be considered a strong security measure one should consider
+ * it as an additional small security obfuscation layer to comply with compliance
+ * guidelines.
+ *
+ * TODO: Remove this in a future relase with an approach such as
+ * https://github.com/owncloud/core/pull/17866
+ *
+ * @package OC\Session
+ */
+class CryptoWrapper {
+ const COOKIE_NAME = 'oc_sessionPassphrase';
+
+ /** @var ISession */
+ protected $session;
+
+ /** @var \OCP\Security\ICrypto */
+ protected $crypto;
+
+ /** @var ISecureRandom */
+ protected $random;
+
+ /**
+ * @param IConfig $config
+ * @param ICrypto $crypto
+ * @param ISecureRandom $random
+ * @param IRequest $request
+ */
+ public function __construct(IConfig $config,
+ ICrypto $crypto,
+ ISecureRandom $random,
+ IRequest $request) {
+ $this->crypto = $crypto;
+ $this->config = $config;
+ $this->random = $random;
+
+ if (!is_null($request->getCookie(self::COOKIE_NAME))) {
+ $this->passphrase = $request->getCookie(self::COOKIE_NAME);
+ } else {
+ $this->passphrase = $this->random->getMediumStrengthGenerator()->generate(128);
+ $secureCookie = $request->getServerProtocol() === 'https';
+ // FIXME: Required for CI
+ if (!defined('PHPUNIT_RUN')) {
+ setcookie(self::COOKIE_NAME, $this->passphrase, 0, \OC::$WEBROOT, '', $secureCookie, true);
+ }
+ }
+ }
+
+ /**
+ * @param ISession $session
+ * @return ISession
+ */
+ public function wrapSession(ISession $session) {
+ if (!($session instanceof CryptoSessionData)) {
+ return new CryptoSessionData($session, $this->crypto, $this->passphrase);
+ }
+
+ return $session;
+ }
+}