diff options
author | ernolf <raphael.gradenwitz@googlemail.com> | 2024-08-15 20:46:46 +0200 |
---|---|---|
committer | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2024-09-28 08:06:24 +0200 |
commit | b4ea146d10506f125c103706026965fc9c1b45ef (patch) | |
tree | ce9b3a17056645fd9b270a7b0c342e41ff921ba8 /lib | |
parent | e202b6c460f35e38a3ece4009562ae618061bf1e (diff) | |
download | nextcloud-server-b4ea146d10506f125c103706026965fc9c1b45ef.tar.gz nextcloud-server-b4ea146d10506f125c103706026965fc9c1b45ef.zip |
feat(share): make sharelink token length configurableernolf/configurable_sharetoken_length
- ensure unique share token with dynamic length adjustment
Signed-off-by: ernolf <raphael.gradenwitz@googlemail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/Share/Constants.php | 5 | ||||
-rw-r--r-- | lib/private/Share/Helper.php | 9 | ||||
-rw-r--r-- | lib/private/Share20/Manager.php | 44 |
3 files changed, 50 insertions, 8 deletions
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php index 8cfa83f9ea2..baff04fbc4a 100644 --- a/lib/private/Share/Constants.php +++ b/lib/private/Share/Constants.php @@ -63,7 +63,10 @@ class Constants { public const RESPONSE_FORMAT = 'json'; // default response format for ocs calls - public const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility + public const MIN_TOKEN_LENGTH = 6; // 19,770,609,664 different possible variations + public const DEFAULT_TOKEN_LENGTH = 15; // 54,960,434,128,018,667,122,720,768 different possible variations + public const MAX_TOKEN_LENGTH = 32; // 8,167,835,760,036,914,488,254,418,108,462,708,901,695,678,621,570,564,096 different possible variations + public const TOKEN_LENGTH = self::DEFAULT_TOKEN_LENGTH; // old (oc7) length is 32, keep token length in db at least that for compatibility protected static $shareTypeUserAndGroups = -1; protected static $shareTypeGroupUserUnique = 2; diff --git a/lib/private/Share/Helper.php b/lib/private/Share/Helper.php index 76e7daeb9e5..d53f9d6ed94 100644 --- a/lib/private/Share/Helper.php +++ b/lib/private/Share/Helper.php @@ -126,4 +126,13 @@ class Helper extends \OC\Share\Constants { return false; } + + public static function getTokenLength(): int { + $config = \OCP\Server::get(\OCP\IAppConfig::class); + $tokenLength = $config->getValueInt('core', 'shareapi_token_length', self::DEFAULT_TOKEN_LENGTH); + $tokenLength = $tokenLength ?: self::DEFAULT_TOKEN_LENGTH; + + // Token length should be within the defined min and max limits + return max(self::MIN_TOKEN_LENGTH, min($tokenLength, self::MAX_TOKEN_LENGTH)); + } } diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 1477560c6fd..f46d163e58a 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -656,13 +656,43 @@ class Manager implements IManager { $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 - ) - ); + // Initial token length + $tokenLength = \OC\Share\Helper::getTokenLength(); + + do { + $tokenExists = false; + + for ($i = 0; $i <= 2; $i++) { + // Generate a new token + $token = $this->secureRandom->generate( + $tokenLength, + \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE + ); + + try { + // Try to fetch a share with the generated token + $this->getShareByToken($token); + $tokenExists = true; // Token exists, we need to try again + } catch (\OCP\Share\Exceptions\ShareNotFound $e) { + // Token is unique, exit the loop + $tokenExists = false; + break; + } + } + + // If we've reached the maximum attempts and the token still exists, increase the token length + if ($tokenExists) { + $tokenLength++; + + // Check if the token length exceeds the maximum allowed length + if ($tokenLength > \OC\Share\Constants::MAX_TOKEN_LENGTH) { + 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); |