diff options
author | Julius Härtl <jus@bitgrid.net> | 2022-03-09 10:52:27 +0100 |
---|---|---|
committer | Vincent Petry (Rebase PR Action) <PVince81@users.noreply.github.com> | 2022-12-05 16:10:55 +0000 |
commit | e4735ea5801d26f38422724086809856525c07c3 (patch) | |
tree | d53d6ba0d4322e7cc89167a5912a23a18bd18637 /lib | |
parent | c7799281430a17f03ce13589f156685c3ac6124b (diff) | |
download | nextcloud-server-e4735ea5801d26f38422724086809856525c07c3.tar.gz nextcloud-server-e4735ea5801d26f38422724086809856525c07c3.zip |
Add fallback routines for empty secret cases
Signed-off-by: Julius Härtl <jus@bitgrid.net>
(cherry picked from commit 81f8719cc0fdc2fc25a00ac1412ffc63cd62eabf)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/Authentication/Token/PublicKeyTokenProvider.php | 19 | ||||
-rw-r--r-- | lib/private/Security/Crypto.php | 9 | ||||
-rw-r--r-- | lib/private/Security/Hasher.php | 9 | ||||
-rw-r--r-- | lib/private/Security/VerificationToken/VerificationToken.php | 9 |
4 files changed, 41 insertions, 5 deletions
diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php index 249f9bd411f..5ccfe3f107f 100644 --- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php +++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php @@ -198,6 +198,7 @@ class PublicKeyTokenProvider implements IProvider { $this->cache->clear(); $this->mapper->invalidate($this->hashToken($token)); + $this->mapper->invalidate($this->hashTokenWithEmptySecret($token)); } public function invalidateTokenById(string $uid, int $id) { @@ -314,9 +315,14 @@ class PublicKeyTokenProvider implements IProvider { try { return $this->crypto->decrypt($cipherText, $token . $secret); } catch (\Exception $ex) { - // Delete the invalid token - $this->invalidateToken($token); - throw new InvalidTokenException("Could not decrypt token password: " . $ex->getMessage(), 0, $ex); + // Retry with empty secret as a fallback for instances where the secret might not have been set by accident + try { + return $this->crypto->decrypt($cipherText, $token); + } catch (\Exception $ex2) { + // Delete the invalid token + $this->invalidateToken($token); + throw new InvalidTokenException("Could not decrypt token password: " . $ex->getMessage(), 0, $ex2); + } } } @@ -340,6 +346,13 @@ class PublicKeyTokenProvider implements IProvider { } /** + * @depreacted Fallback for instances where the secret might not have been set by accident + */ + private function hashTokenWithEmptySecret(string $token): string { + return hash('sha512', $token); + } + + /** * @throws \RuntimeException when OpenSSL reports a problem */ private function newToken(string $token, diff --git a/lib/private/Security/Crypto.php b/lib/private/Security/Crypto.php index e9ef4417925..d3b62dc7e4d 100644 --- a/lib/private/Security/Crypto.php +++ b/lib/private/Security/Crypto.php @@ -125,6 +125,15 @@ class Crypto implements ICrypto { if ($password === '') { $password = $this->config->getSystemValue('secret'); } + try { + return $this->decryptWithoutSecret($authenticatedCiphertext, $password); + } catch (Exception $e) { + // Retry with empty secret as a fallback for instances where the secret might not have been set by accident + return $this->decryptWithoutSecret($authenticatedCiphertext, ''); + } + } + + private function decryptWithoutSecret(string $authenticatedCiphertext, string $password = ''): string { $hmacKey = $encryptionKey = $password; $parts = explode('|', $authenticatedCiphertext); diff --git a/lib/private/Security/Hasher.php b/lib/private/Security/Hasher.php index 5b3fc2b47a9..4731ba96bd3 100644 --- a/lib/private/Security/Hasher.php +++ b/lib/private/Security/Hasher.php @@ -137,6 +137,15 @@ class Hasher implements IHasher { return true; } + // Verify whether it matches a legacy PHPass or SHA1 string + // Retry with empty passwordsalt for cases where it was not set + $hashLength = \strlen($hash); + if (($hashLength === 60 && password_verify($message, $hash)) || + ($hashLength === 40 && hash_equals($hash, sha1($message)))) { + $newHash = $this->hash($message); + return true; + } + return false; } diff --git a/lib/private/Security/VerificationToken/VerificationToken.php b/lib/private/Security/VerificationToken/VerificationToken.php index c85e0e7b5a1..2d3f902b622 100644 --- a/lib/private/Security/VerificationToken/VerificationToken.php +++ b/lib/private/Security/VerificationToken/VerificationToken.php @@ -84,10 +84,15 @@ class VerificationToken implements IVerificationToken { try { $decryptedToken = $this->crypto->decrypt($encryptedToken, $passwordPrefix.$this->config->getSystemValue('secret')); } catch (\Exception $e) { - $this->throwInvalidTokenException(InvalidTokenException::TOKEN_DECRYPTION_ERROR); + // Retry with empty secret as a fallback for instances where the secret might not have been set by accident + try { + $decryptedToken = $this->crypto->decrypt($encryptedToken, $passwordPrefix); + } catch (\Exception $e2) { + $this->throwInvalidTokenException(InvalidTokenException::TOKEN_DECRYPTION_ERROR); + } } - $splitToken = explode(':', $decryptedToken ?? ''); + $splitToken = explode(':', $decryptedToken); if (count($splitToken) !== 2) { $this->throwInvalidTokenException(InvalidTokenException::TOKEN_INVALID_FORMAT); } |