diff options
Diffstat (limited to 'lib/private/User/Session.php')
-rw-r--r-- | lib/private/User/Session.php | 139 |
1 files changed, 43 insertions, 96 deletions
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 3f893eb9bae..e7bfcf56407 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -1,40 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2017, Sandro Lutz <sandro.lutz@temparus.ch> - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Felix Rupp <github@felixrupp.com> - * @author Greta Doci <gretadoci@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Lionel Elie Mamane <lionel@mamane.lu> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sandro Lutz <sandro.lutz@temparus.ch> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <vincent@nextcloud.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: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OC\User; @@ -43,12 +12,15 @@ use OC\Authentication\Exceptions\PasswordlessTokenException; use OC\Authentication\Exceptions\PasswordLoginForbiddenException; use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IToken; +use OC\Authentication\Token\PublicKeyToken; use OC\Authentication\TwoFactorAuth\Manager as TwoFactorAuthManager; use OC\Hooks\Emitter; use OC\Hooks\PublicEmitter; +use OC\Security\CSRF\CsrfTokenManager; use OC_User; use OC_Util; use OCA\DAV\Connector\Sabre\Auth; +use OCP\AppFramework\Db\TTransactional; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Authentication\Exceptions\ExpiredTokenException; use OCP\Authentication\Exceptions\InvalidTokenException; @@ -56,6 +28,7 @@ use OCP\EventDispatcher\GenericEvent; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\NotPermittedException; use OCP\IConfig; +use OCP\IDBConnection; use OCP\IRequest; use OCP\ISession; use OCP\IUser; @@ -92,53 +65,22 @@ use Psr\Log\LoggerInterface; * @package OC\User */ class Session implements IUserSession, Emitter { - /** @var Manager $manager */ - private $manager; - - /** @var ISession $session */ - private $session; - - /** @var ITimeFactory */ - private $timeFactory; - - /** @var IProvider */ - private $tokenProvider; - - /** @var IConfig */ - private $config; + use TTransactional; /** @var User $activeUser */ protected $activeUser; - /** @var ISecureRandom */ - private $random; - - /** @var ILockdownManager */ - private $lockdownManager; - - private LoggerInterface $logger; - /** @var IEventDispatcher */ - private $dispatcher; - - public function __construct(Manager $manager, - ISession $session, - ITimeFactory $timeFactory, - ?IProvider $tokenProvider, - IConfig $config, - ISecureRandom $random, - ILockdownManager $lockdownManager, - LoggerInterface $logger, - IEventDispatcher $dispatcher + public function __construct( + private Manager $manager, + private ISession $session, + private ITimeFactory $timeFactory, + private ?IProvider $tokenProvider, + private IConfig $config, + private ISecureRandom $random, + private ILockdownManager $lockdownManager, + private LoggerInterface $logger, + private IEventDispatcher $dispatcher, ) { - $this->manager = $manager; - $this->session = $session; - $this->timeFactory = $timeFactory; - $this->tokenProvider = $tokenProvider; - $this->config = $config; - $this->random = $random; - $this->lockdownManager = $lockdownManager; - $this->logger = $logger; - $this->dispatcher = $dispatcher; } /** @@ -378,7 +320,7 @@ class Session implements IUserSession, Emitter { // disabled users can not log in // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory $message = \OCP\Util::getL10N('lib')->t('Account disabled'); - throw new LoginException($message); + throw new DisabledUserException($message); } if ($regenerateSessionId) { @@ -393,6 +335,7 @@ class Session implements IUserSession, Emitter { if ($isToken) { $this->setToken($loginDetails['token']->getId()); $this->lockdownManager->setToken($loginDetails['token']); + $user->updateLastLoginTimestamp(); $firstTimeLogin = false; } else { $this->setToken(null); @@ -562,7 +505,7 @@ class Session implements IUserSession, Emitter { if ($refreshCsrfToken) { // TODO: mock/inject/use non-static // Refresh the token - \OC::$server->getCsrfTokenManager()->refreshToken(); + \OC::$server->get(CsrfTokenManager::class)->refreshToken(); } if ($firstTimeLogin) { @@ -704,8 +647,10 @@ class Session implements IUserSession, Emitter { $sessionId = $this->session->getId(); $pwd = $this->getPassword($password); // Make sure the current sessionId has no leftover tokens - $this->tokenProvider->invalidateToken($sessionId); - $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember); + $this->atomic(function () use ($sessionId, $uid, $loginName, $pwd, $name, $remember) { + $this->tokenProvider->invalidateToken($sessionId); + $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember); + }, \OCP\Server::get(IDBConnection::class)); return true; } catch (SessionNotAvailableException $ex) { // This can happen with OCC, where a memory session is used @@ -767,8 +712,6 @@ class Session implements IUserSession, Emitter { return false; } - $dbToken->setLastCheck($now); - $this->tokenProvider->updateToken($dbToken); return true; } @@ -786,6 +729,9 @@ class Session implements IUserSession, Emitter { } $dbToken->setLastCheck($now); + if ($dbToken instanceof PublicKeyToken) { + $dbToken->setLastActivity($now); + } $this->tokenProvider->updateToken($dbToken); return true; } @@ -835,7 +781,7 @@ class Session implements IUserSession, Emitter { * Check if login names match */ private function validateTokenLoginName(?string $loginName, IToken $token): bool { - if ($token->getLoginName() !== $loginName) { + if (mb_strtolower($token->getLoginName()) !== mb_strtolower($loginName ?? '')) { // TODO: this makes it impossible to use different login names on browser and client // e.g. login by e-mail 'user@example.com' on browser for generating the token will not // allow to use the client token with the login name 'user'. @@ -889,9 +835,8 @@ class Session implements IUserSession, Emitter { return true; } - // Remember me tokens are not app_passwords - if ($dbToken->getRemember() === IToken::DO_NOT_REMEMBER) { - // Set the session variable so we know this is an app password + // Set the session variable so we know this is an app password + if ($dbToken instanceof PublicKeyToken && $dbToken->getType() === IToken::PERMANENT_TOKEN) { $this->session->set('app_password', $token); } @@ -1023,6 +968,7 @@ class Session implements IUserSession, Emitter { if ($webRoot === '') { $webRoot = '/'; } + $domain = $this->config->getSystemValueString('cookie_domain'); $maxAge = $this->config->getSystemValueInt('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); \OC\Http\CookieHelper::setCookie( @@ -1030,7 +976,7 @@ class Session implements IUserSession, Emitter { $username, $maxAge, $webRoot, - '', + $domain, $secureCookie, true, \OC\Http\CookieHelper::SAMESITE_LAX @@ -1040,7 +986,7 @@ class Session implements IUserSession, Emitter { $token, $maxAge, $webRoot, - '', + $domain, $secureCookie, true, \OC\Http\CookieHelper::SAMESITE_LAX @@ -1051,7 +997,7 @@ class Session implements IUserSession, Emitter { $this->session->getId(), $maxAge, $webRoot, - '', + $domain, $secureCookie, true, \OC\Http\CookieHelper::SAMESITE_LAX @@ -1067,18 +1013,19 @@ class Session implements IUserSession, Emitter { public function unsetMagicInCookie() { //TODO: DI for cookies and IRequest $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https'; + $domain = $this->config->getSystemValueString('cookie_domain'); unset($_COOKIE['nc_username']); //TODO: DI unset($_COOKIE['nc_token']); unset($_COOKIE['nc_session_id']); - setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true); - setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true); - setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true); + setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, $domain, $secureCookie, true); + setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, $domain, $secureCookie, true); + setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, $domain, $secureCookie, true); // old cookies might be stored under /webroot/ instead of /webroot // and Firefox doesn't like it! - setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); - setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); - setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); + setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', $domain, $secureCookie, true); + setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', $domain, $secureCookie, true); + setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', $domain, $secureCookie, true); } /** |