Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(share): make sharelink token length configurable #47265

Merged
merged 1 commit into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lib/private/Share/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions lib/private/Share/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,13 @@ public static function isSameUserOnSameServer($user1, $server1, $user2, $server2

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));
}
}
44 changes: 37 additions & 7 deletions lib/private/Share20/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -656,13 +656,43 @@ 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
)
);
// 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);
Expand Down
Loading