Page MenuHomePhorge

D5265.1774834783.diff
No OneTemporary

Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None

D5265.1774834783.diff

diff --git a/src/app/User.php b/src/app/User.php
--- a/src/app/User.php
+++ b/src/app/User.php
@@ -765,17 +765,35 @@
if (!empty($this->password)) {
$authenticated = Hash::check($password, $this->password);
} elseif (!empty($this->password_ldap)) {
- if (substr($this->password_ldap, 0, 6) == "{SSHA}") {
- $salt = substr(base64_decode(substr($this->password_ldap, 6)), 20);
- $hash = '{SSHA}' . base64_encode(sha1($password . $salt, true) . $salt);
-
- $authenticated = $hash === $this->password_ldap;
- } elseif (substr($this->password_ldap, 0, 9) == "{SSHA512}") {
- $salt = substr(base64_decode(substr($this->password_ldap, 9)), 64);
- $hash = '{SSHA512}' . base64_encode(pack('H*', hash('sha512', $password . $salt)) . $salt);
-
- $authenticated = $hash === $this->password_ldap;
+ if (preg_match('/^\{([A-Z0-9_-]+)\}/', $this->password_ldap, $matches)) {
+ switch ($matches[1]) {
+ case 'SSHA':
+ $salt = substr(base64_decode(substr($this->password_ldap, 6)), 20);
+ $hash = '{SSHA}' . base64_encode(sha1($password . $salt, true) . $salt);
+ break;
+ case 'SSHA512':
+ $salt = substr(base64_decode(substr($this->password_ldap, 9)), 64);
+ $hash = '{SSHA512}' . base64_encode(pack('H*', hash('sha512', $password . $salt)) . $salt);
+ break;
+ case 'PBKDF2_SHA256':
+ // Algorithm based on https://github.com/thesubtlety/389-ds-password-check/blob/master/389ds-pwdcheck.py
+ $decoded = base64_decode(substr($this->password_ldap, 15));
+ $param = unpack('Niterations/a64salt', $decoded);
+ $hash = hash_pbkdf2('sha256', $password, $param['salt'], $param['iterations'], 256, true);
+ $hash = '{' . $matches[1] . '}' . base64_encode(substr($decoded, 0, 68) . $hash);
+ break;
+ case 'PBKDF2-SHA512':
+ [, $algo] = explode('-', $matches[1]);
+ [$iterations, $salt] = explode('$', substr($this->password_ldap, 15));
+ $hash = hash_pbkdf2($algo, $password, base64_decode($salt), (int) $iterations, 0, true);
+ $hash = '{' . $matches[1] . '}' . $iterations . '$' . $salt . '$' . base64_encode($hash);
+ break;
+ default:
+ \Log::warning("Unsupported password hashing algorithm {$matches[1]}");
+ }
}
+
+ $authenticated = isset($hash) && $hash === $this->password_ldap;
} else {
\Log::error("Missing password for {$this->email}");
}
diff --git a/src/tests/Feature/UserTest.php b/src/tests/Feature/UserTest.php
--- a/src/tests/Feature/UserTest.php
+++ b/src/tests/Feature/UserTest.php
@@ -1730,7 +1730,32 @@
$this->assertTrue($user->password_ldap == $ldap); // @phpstan-ignore-line
$this->assertTrue(strlen($user->password) == strlen($hash)); // @phpstan-ignore-line
- // TODO: sha1 passwords in password_ldap (or remove this code)
+ // Test PBKDF2-SHA512 algorithm (389-ds)
+ $pass = '{PBKDF2-SHA512}10000$hbMHmUXNh3UoHNlDu+NJBOW+hVAhP3C0$ax9vNLL1rr85ppODFTykPC46igHh92v'
+ . 'ULWpZaR/CQqyD4IGG/IyPYbbC2v7BxSPIDUXc0e9AGX9IuwinIj5a/w==';
+ $user->setRawAttributes(array_merge($attrs, ['password_ldap' => $pass, 'password' => null]));
+
+ $this->assertTrue($user->validatePassword('12345678_kolab'));
+ $this->assertFalse($user->validatePassword('badpass'));
+
+ // Test SSHA algorithm
+ $pass = '{SSHA}kor2Qo2qEsP1XojQe3esWFB8IvYKqwUH';
+ $user->setRawAttributes(array_merge($attrs, ['password_ldap' => $pass, 'password' => null]));
+
+ $this->assertTrue($user->validatePassword('test123'));
+ $this->assertFalse($user->validatePassword('badpass'));
+
+ // Test PBKDF2_SHA256 algorithm (389-ds)
+ $pass = '{PBKDF2_SHA256}AAAIABzpVq0s1Ta7cqubx+19QOzsI7n7KRLu0SovLVivxUVCn0+ghlj3+9+tf3jqurd'
+ . 'QhpQ/OWYmxMlAJCAeIU3jN0DDW7ODk9FpLFzhO2055J+vY5M7EXAGrvhUlkiyeH/zx/RBp2pVQq/2vtI+qmO'
+ . 'GOGUXdZ0hK00yNXpZ7K7WTwsnEXeWs4DGkGkxwyPgsGTyEwwdYK4YpCFdjJi/dXI6+kKf72j+B+epuzPtuvd'
+ . 'Mj5xGnqe9jS+BN9Huzkof4vRPX3bYecywPaeNcdXPUY3iSj8hxFqiWbBDZ0mYy9aYAy6QgMitcdEGadPcR+d'
+ . 'HXWNGK1qSLrFJJrB3cQtYhl+OgtHlwI0H4XTGBdp4MbegM3VgpUKuBNyIypwZ5oB/PRHA188bmsMjDmyN2kE'
+ . 'nHSb1CK9MXcuS4bCQzNtutmQCxBCo';
+ $user->setRawAttributes(array_merge($attrs, ['password_ldap' => $pass, 'password' => null]));
+
+ $this->assertTrue($user->validatePassword('Simple321Simple321'));
+ $this->assertFalse($user->validatePassword('badpass'));
}
/**

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 30, 1:39 AM (3 d, 20 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18786087
Default Alt Text
D5265.1774834783.diff (4 KB)

Event Timeline