diff options
Diffstat (limited to 'lib/private/Session/CryptoSessionData.php')
-rw-r--r-- | lib/private/Session/CryptoSessionData.php | 84 |
1 files changed, 50 insertions, 34 deletions
diff --git a/lib/private/Session/CryptoSessionData.php b/lib/private/Session/CryptoSessionData.php index 2e3bd46da5b..323253af534 100644 --- a/lib/private/Session/CryptoSessionData.php +++ b/lib/private/Session/CryptoSessionData.php @@ -1,42 +1,24 @@ <?php declare(strict_types=1); - /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Victor Dubiniuk <dubiniuk@owncloud.com> - * - * @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/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OC\Session; use OCP\ISession; use OCP\Security\ICrypto; use OCP\Session\Exceptions\SessionNotAvailableException; +use function json_decode; +use function OCP\Log\logger; /** * Class CryptoSessionData * * @package OC\Session + * @template-implements \ArrayAccess<string,mixed> */ class CryptoSessionData implements \ArrayAccess, ISession { /** @var ISession */ @@ -57,8 +39,8 @@ class CryptoSessionData implements \ArrayAccess, ISession { * @param string $passphrase */ public function __construct(ISession $session, - ICrypto $crypto, - string $passphrase) { + ICrypto $crypto, + string $passphrase) { $this->crypto = $crypto; $this->session = $session; $this->passphrase = $passphrase; @@ -79,14 +61,24 @@ class CryptoSessionData implements \ArrayAccess, ISession { protected function initializeSession() { $encryptedSessionData = $this->session->get(self::encryptedSessionName) ?: ''; - try { - $this->sessionValues = json_decode( - $this->crypto->decrypt($encryptedSessionData, $this->passphrase), - true - ); - } catch (\Exception $e) { + if ($encryptedSessionData === '') { + // Nothing to decrypt $this->sessionValues = []; - $this->regenerateId(true, false); + } else { + try { + $this->sessionValues = json_decode( + $this->crypto->decrypt($encryptedSessionData, $this->passphrase), + true, + 512, + JSON_THROW_ON_ERROR, + ); + } catch (\Exception $e) { + logger('core')->critical('Could not decrypt or decode encrypted session data', [ + 'exception' => $e, + ]); + $this->sessionValues = []; + $this->regenerateId(true, false); + } } } @@ -97,8 +89,17 @@ class CryptoSessionData implements \ArrayAccess, ISession { * @param mixed $value */ public function set(string $key, $value) { + if ($this->get($key) === $value) { + // Do not write the session if the value hasn't changed to avoid reopening + return; + } + + $reopened = $this->reopen(); $this->sessionValues[$key] = $value; $this->isModified = true; + if ($reopened) { + $this->close(); + } } /** @@ -131,15 +132,19 @@ class CryptoSessionData implements \ArrayAccess, ISession { * @param string $key */ public function remove(string $key) { + $reopened = $this->reopen(); $this->isModified = true; unset($this->sessionValues[$key]); - $this->session->remove(self::encryptedSessionName); + if ($reopened) { + $this->close(); + } } /** * Reset and recreate the session */ public function clear() { + $reopened = $this->reopen(); $requesttoken = $this->get('requesttoken'); $this->sessionValues = []; if ($requesttoken !== null) { @@ -147,6 +152,17 @@ class CryptoSessionData implements \ArrayAccess, ISession { } $this->isModified = true; $this->session->clear(); + if ($reopened) { + $this->close(); + } + } + + public function reopen(): bool { + $reopened = $this->session->reopen(); + if ($reopened) { + $this->initializeSession(); + } + return $reopened; } /** |