Skip to content

Commit

Permalink
Merge pull request #316 from Pylons/tseaver-315-password_verification…
Browse files Browse the repository at this point in the history
…_w_bcrypt

fix: password check for users created prior to use of 'bcrypt'
  • Loading branch information
tseaver authored Sep 1, 2024
2 parents 71c3e6c + 42b5d45 commit 7998a16
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
1.0b1 (unreleased)
==================

- Fix password check for users created prior to switching to ``bcrypt``.
See https://github.com/Pylons/substanced/pull/316

- Fix ``tznames_widget``, b0rken seemingly forever under Python3.
See https://github.com/Pylons/substanced/pull/314

Expand Down
14 changes: 10 additions & 4 deletions substanced/principal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,17 +407,23 @@ def timezone(self):
return pytz.timezone(self.tzname)

def check_password(self, password):
""" Checks if the plaintext password passed as ``password`` matches
this user's stored, encrypted password. Returns ``True`` or
``False``."""
"""Check plaintext ``password`` against stored, hashed password.
"""
statsd_gauge('check_password', 1)

if len(password) > 4096:
# avoid DOS ala
# https://www.djangoproject.com/weblog/2013/sep/15/security/
raise ValueError('Not checking password > 4096 bytes')

if isinstance(password, str):
password = password.encode('utf-8')
return bcrypt.checkpw(password, self.password)

hashed = self.password
if isinstance(hashed, str):
hashed = hashed.encode('utf-8')

return bcrypt.checkpw(password, hashed)

def set_password(self, password):
self.password = self.hash_new_password(password)
Expand Down
8 changes: 8 additions & 0 deletions substanced/principal/tests/test_principal.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,14 @@ def test_check_password(self):
self.assertTrue(inst.check_password('abc'))
self.assertFalse(inst.check_password('abcdef'))

def test_check_password_w_str(self):
inst = self._makeOne('abc')
assert isinstance(inst.password, bytes)
# See https://github.com/Pylons/substanced/issues/315
inst.password = inst.password.decode('utf8')
self.assertTrue(inst.check_password('abc'))
self.assertFalse(inst.check_password('abcdef'))

def test_check_password_gt_4096_bytes(self):
inst = self._makeOne('abc')
self.assertRaises(ValueError, inst.check_password, 'a'*4097)
Expand Down

0 comments on commit 7998a16

Please sign in to comment.