Merge pull request #47265 from nextcloud/ernolf/configurable_sharetoken_length

feat(share): make sharelink token length configurable
pull/48424/head
Joas Schilling 2024-09-28 08:34:57 +07:00 committed by GitHub
commit c470ef0fd7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 50 additions and 8 deletions

@ -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;

@ -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));
}
}

@ -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);