diff --git a/modoboa/admin/tests/test_password_schemes.py b/modoboa/admin/tests/test_password_schemes.py index 28b1331b7..f19ba7bf3 100644 --- a/modoboa/admin/tests/test_password_schemes.py +++ b/modoboa/admin/tests/test_password_schemes.py @@ -34,6 +34,9 @@ class PasswordSchemesTestCase(ModoTestCase): self.assertTrue(account.password.startswith(startpattern)) self.assertTrue(account.check_password('Toto1234')) + def test_bcrypt_scheme(self): + self._test_scheme('blfcrypt', '{BLF-CRYPT}') + def test_sha512crypt_scheme(self): self._test_scheme('sha512crypt', '{SHA512-CRYPT}') diff --git a/modoboa/core/app_settings.py b/modoboa/core/app_settings.py index 648f02215..ee35f1598 100644 --- a/modoboa/core/app_settings.py +++ b/modoboa/core/app_settings.py @@ -48,6 +48,7 @@ class GeneralParametersForm(parameters.AdminParametersForm): label=ugettext_lazy("Default password scheme"), choices=[("sha512crypt", "sha512crypt"), ("sha256crypt", "sha256crypt"), + ("blfcrypt", "bcrypt"), ("md5crypt", ugettext_lazy("md5crypt (weak)")), ("sha256", ugettext_lazy("sha256 (weak)")), ("md5", ugettext_lazy("md5 (weak)")), diff --git a/modoboa/core/password_hashers/__init__.py b/modoboa/core/password_hashers/__init__.py index 66e4d6a64..653b0dd56 100644 --- a/modoboa/core/password_hashers/__init__.py +++ b/modoboa/core/password_hashers/__init__.py @@ -5,7 +5,7 @@ from modoboa.core.password_hashers.base import ( PLAINHasher, CRYPTHasher, MD5Hasher, SHA256Hasher ) from modoboa.core.password_hashers.advanced import ( - MD5CRYPTHasher, SHA256CRYPTHasher, SHA512CRYPTHasher + BLFCRYPTHasher, MD5CRYPTHasher, SHA256CRYPTHasher, SHA512CRYPTHasher ) diff --git a/modoboa/core/password_hashers/advanced.py b/modoboa/core/password_hashers/advanced.py index 73b5ef493..55915e6db 100644 --- a/modoboa/core/password_hashers/advanced.py +++ b/modoboa/core/password_hashers/advanced.py @@ -3,10 +3,36 @@ Advanced (ie. stronger) password hashers. This module relies on `passlib` to provide more secure hashers. """ -from passlib.hash import md5_crypt, sha256_crypt, sha512_crypt +from passlib.hash import bcrypt, md5_crypt, sha256_crypt, sha512_crypt from modoboa.core.password_hashers.base import PasswordHasher from modoboa.lib import parameters +class BLFCRYPTHasher(PasswordHasher): + """ + BLF-CRYPT password hasher. + + Supports rounds and provides compatibility with dovecot on + *BSD systems. + """ + @property + def scheme(self): + return '{BLF-CRYPT}' if self._target == 'local' else '{CRYPT}' + + def _b64encode(self, pwhash): + return pwhash + + def _encrypt(self, clearvalue, salt=None): + # Using the parameter for rounds will generate the error + # ValueError: rounds too high (bcrypt requires <= 31 rounds) + # when using the bcrypt hasher. + #rounds = int(parameters.get_admin('ROUNDS_NUMBER')) + # To get around this, I use the default of 12. + rounds = 12 + return bcrypt.encrypt(clearvalue, rounds=rounds) + + def verify(self, clearvalue, hashed_value): + return bcrypt.verify(clearvalue, hashed_value) + class MD5CRYPTHasher(PasswordHasher):