Browse Source

Allow updating the token on session regeneration

Sometimes when we force a session regeneration we want to update the
current token for this session.

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Roeland Jago Douma 6 years ago
parent
commit
8c47a632e0

+ 1 - 1
apps/files_sharing/lib/Controller/ShareController.php

@@ -217,7 +217,7 @@ class ShareController extends Controller {
 	private function linkShareAuth(\OCP\Share\IShare $share, $password = null) {
 		if ($password !== null) {
 			if ($this->shareManager->checkPassword($share, $password)) {
-				$this->session->regenerateId();
+				$this->session->regenerateId(true, true);
 				$this->session->set('public_link_authenticated', (string)$share->getId());
 			} else {
 				$this->emitAccessShareHook($share, 403, 'Wrong password');

+ 3 - 2
lib/private/Session/CryptoSessionData.php

@@ -150,10 +150,11 @@ class CryptoSessionData implements \ArrayAccess, ISession {
 	 * Wrapper around session_regenerate_id
 	 *
 	 * @param bool $deleteOldSession Whether to delete the old associated session file or not.
+	 * @param bool $updateToken Wheater to update the associated auth token
 	 * @return void
 	 */
-	public function regenerateId(bool $deleteOldSession = true) {
-		$this->session->regenerateId($deleteOldSession);
+	public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {
+		$this->session->regenerateId($deleteOldSession, $updateToken);
 	}
 
 	/**

+ 32 - 1
lib/private/Session/Internal.php

@@ -30,6 +30,10 @@ declare(strict_types=1);
 
 namespace OC\Session;
 
+use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Token\IProvider;
+use OC\SystemConfig;
+use OCP\IConfig;
 use OCP\Session\Exceptions\SessionNotAvailableException;
 
 /**
@@ -111,14 +115,41 @@ class Internal extends Session {
 	 * Wrapper around session_regenerate_id
 	 *
 	 * @param bool $deleteOldSession Whether to delete the old associated session file or not.
+	 * @param bool $updateToken Wheater to update the associated auth token
 	 * @return void
 	 */
-	public function regenerateId(bool $deleteOldSession = true) {
+	public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {
+		$oldId = null;
+
+		if ($updateToken) {
+			// Get the old id to update the token
+			try {
+				$oldId = $this->getId();
+			} catch (SessionNotAvailableException $e) {
+				// We can't update a token if there is no previous id
+				$updateToken = false;
+			}
+		}
+
 		try {
 			@session_regenerate_id($deleteOldSession);
 		} catch (\Error $e) {
 			$this->trapError($e->getCode(), $e->getMessage());
 		}
+
+		if ($updateToken) {
+			// Get the new id to update the token
+			$newId = $this->getId();
+
+			/** @var IProvider $tokenProvider */
+			$tokenProvider = \OC::$server->query(IProvider::class);
+
+			try {
+				$tokenProvider->renewSessionToken($oldId, $newId);
+			} catch (InvalidTokenException $e) {
+				// Just ignore
+			}
+		}
 	}
 
 	/**

+ 1 - 1
lib/private/Session/Memory.php

@@ -91,7 +91,7 @@ class Memory extends Session {
 	 *
 	 * @param bool $deleteOldSession
 	 */
-	public function regenerateId(bool $deleteOldSession = true) {}
+	public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {}
 
 	/**
 	 * Wrapper around session_id

+ 2 - 0
lib/private/User/Session.php

@@ -626,6 +626,8 @@ class Session implements IUserSession, Emitter {
 		try {
 			$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);
 			return true;
 		} catch (SessionNotAvailableException $ex) {

+ 3 - 2
lib/public/ISession.php

@@ -96,10 +96,11 @@ interface ISession {
 	 * Wrapper around session_regenerate_id
 	 *
 	 * @param bool $deleteOldSession Whether to delete the old associated session file or not.
+	 * @param bool $updateToken Wheater to update the associated auth token
 	 * @return void
-	 * @since 9.0.0
+	 * @since 9.0.0, $updateToken added in 14.0.0
 	 */
-	public function regenerateId(bool $deleteOldSession = true);
+	public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false);
 
 	/**
 	 * Wrapper around session_id