From 33f7590f4ebc038e2ccf11825c7706e015da9b79 Mon Sep 17 00:00:00 2001 From: ernolf Date: Tue, 20 Aug 2024 12:33:28 +0200 Subject: [PATCH] feat(share): ensure unique share tokens with dynamic length adjustment - check for token collisions and retry up to three times. - abort with an error if maximum token length is reached without finding a unique token. Signed-off-by: ernolf --- lib/private/Share20/Manager.php | 36 ++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 55e10602e7260..d440f8610e3b1 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -665,13 +665,35 @@ public function createShare(IShare $share) { $this->linkCreateChecks($share); $this->setLinkParent($share); - // For now ignore a set token. - $share->setToken( - $this->secureRandom->generate( - \OC\Share\Constants::TOKEN_LENGTH, - \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE - ) - ); + do { + $tokenExists = false; + $attempts = 0; + + do { + // Generate a new token + $token = $this->secureRandom->generate( + \OC\Share\Constants::TOKEN_LENGTH, + \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE + ); + + try { + // Try to fetch a share with the generated token + $this->getShareByToken($token); + $tokenExists = true; // Token exists, generate a new one + $attempts++; // Increment the attempt counter + } catch (\OCP\Share\Exceptions\ShareNotFound $e) { + $tokenExists = false; // Token is unique, we can use it + } + } while ($tokenExists && $attempts < 3); + + // If we've reached the maximum attempts and the token still exists, increase the token length + if ($tokenExists) { + throw new \Exception('Unable to generate a unique share token. Maximum token length exceeded.'); + } + } while ($tokenExists); + + // Set the unique token + $share->setToken($token); // Verify the expiration date $share = $this->validateExpirationDateLink($share);