aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Security
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2022-03-09 10:52:27 +0100
committerJulius Härtl <jus@bitgrid.net>2022-03-10 14:01:21 +0100
commit81f8719cc0fdc2fc25a00ac1412ffc63cd62eabf (patch)
tree29a00c4a12ae2e27d7514dfbcb85cd54c1618b71 /lib/private/Security
parent0825c3ea34675b12bf14dc00354e0ab1c77ecf11 (diff)
downloadnextcloud-server-81f8719cc0fdc2fc25a00ac1412ffc63cd62eabf.tar.gz
nextcloud-server-81f8719cc0fdc2fc25a00ac1412ffc63cd62eabf.zip
Add fallback routines for empty secret cases
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'lib/private/Security')
-rw-r--r--lib/private/Security/Crypto.php9
-rw-r--r--lib/private/Security/Hasher.php9
-rw-r--r--lib/private/Security/VerificationToken/VerificationToken.php9
3 files changed, 25 insertions, 2 deletions
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);
}