3adbfbfd69
When an empty string is used as cookie path PHP will assign the current directory as cookie path. This means when an user had installed an ownCloud under "/", which is mapped to an empty string in \OC::$WEBROOT, and accessed it the cookie was set to values such as "/index.php/apps/files" since the web browser assumed this to be a directory. This means that multiple encryption cookies were set for the same domain resulting in potential havoc. With this patch the path will be set to "/" in case an empty web root is installed which makes the cookie accessible to the whole domain. To test this setup multiple ownCloud instances on the same domain under different ports and have both installed under "/", then try to login in both of it and previously this can in some cases lead to a lockout of the user. Note that this affects the cookies that the browsers do sent and thus to test this you need to clear all cookies from your browser previously. I consider this an acceptable behaviour for now since this code is only in master. Fixes https://github.com/owncloud/core/issues/18919
100 lines
2.9 KiB
PHP
100 lines
2.9 KiB
PHP
<?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')) {
|
|
$webRoot = \OC::$WEBROOT;
|
|
if($webRoot === '') {
|
|
$webRoot = '/';
|
|
}
|
|
setcookie(self::COOKIE_NAME, $this->passphrase, 0, $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;
|
|
}
|
|
}
|