Skip to content

Commit 34092eb

Browse files
committed
Attempt LDAP bind if password hash isn't Argon2
When using an LDAP server with a password hash scheme other than Argon2, Quality-time would not attempt an LDAP bind to verify the user. Fixes #12595.
1 parent 6c7b764 commit 34092eb

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

components/api_server/src/routes/auth.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,13 @@ def set_session_cookie(session_id: SessionId, expires_datetime: datetime) -> Non
5454
bottle.response.set_cookie("session_id", session_id, **options)
5555

5656

57-
def check_password(password_hash, password) -> bool:
57+
def check_password(password_hash: bytes, password: str) -> bool:
5858
"""Check the OpenLDAP password hash against the given password."""
5959
# Note we currently only support ARGON2 hashes
60-
return argon2.PasswordHasher().verify(password_hash.decode().removeprefix("{ARGON2}"), password)
60+
decoded_hash = password_hash.decode()
61+
if decoded_hash.startswith("{ARGON2}"):
62+
return argon2.PasswordHasher().verify(decoded_hash.removeprefix("{ARGON2}"), password)
63+
return False
6164

6265

6366
def get_credentials() -> tuple[str, str]:

components/api_server/tests/routes/test_auth.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,17 +198,17 @@ def test_login_search_error(self, logging_mock, connection_mock, connection_ente
198198
self.ldap_connection.bind.assert_called_once()
199199
self.assert_log(logger.exception, exceptions.LDAPResponseTimeoutError)
200200

201-
@patch("logging.getLogger")
202-
def test_login_password_hash_error(self, logging_mock, connection_mock, connection_enter):
203-
"""Test login fails when LDAP password hash is not ARGON2."""
204-
logger = logging_mock.return_value = Mock()
201+
@patch("routes.auth.datetime", MOCK_DATETIME)
202+
def test_login_no_argon2(self, connection_mock, connection_enter):
203+
"""Test login proceeds with LDAP bind when LDAP password hash is not ARGON2."""
205204
connection_mock.return_value = None
206205
self.ldap_entry.userPassword.value = b"{XSHA}whatever-here"
207206
connection_enter.return_value = self.ldap_connection
208-
self.assertEqual(self.login_nok, login(self.database))
207+
self.assertEqual(self.login_ok, login(self.database))
208+
self.assert_cookie_has_session_id()
209+
self.assert_ldap_lookup_connection_created(connection_mock)
210+
self.assert_ldap_bind_connection_created(connection_mock)
209211
self.assert_ldap_connection_search_called()
210-
self.assertEqual(self.LOG_ERROR_MESSAGE_TEMPLATE, logger.exception.call_args_list[0][0][0])
211-
self.assert_log(logger.exception, argon2.exceptions.InvalidHashError)
212212

213213
@patch("logging.getLogger")
214214
def test_login_wrong_password(self, logging_mock, connection_mock, connection_enter):

docs/src/changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ If your currently installed *Quality-time* version is not the penultimate versio
1010

1111
<!-- The line "## <square-bracket>Unreleased</square-bracket>" is replaced by the release/release.py script with the new release version and release date. -->
1212

13+
## [Unreleased]
14+
15+
### Fixed
16+
17+
- When using an LDAP server with a password hash scheme other than Argon2, Quality-time would not attempt an LDAP bind to verify the user. Fixes [#12595](https://github.com/ICTU/quality-time/issues/12595).
18+
1319
## v5.48.3 - 2026-01-29
1420

1521
### Fixed

0 commit comments

Comments
 (0)