From 239e4f64c2134338b32ffd6d42c0b6ff70cd040c Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Fri, 16 Mar 2012 21:46:31 -0400 Subject: [PATCH] Add check for MAX_PASSWORD_LENGTH to utils. Updates to keystone password hashing and checking functions so that a max password length is enforced. Fixes LP Bug #959288. Change-Id: Id3048f3c916e92c59ac5b063d09c3d612d51c97c --- keystone/common/utils.py | 17 +++++++++++++---- tests/test_utils.py | 5 +++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/keystone/common/utils.py b/keystone/common/utils.py index 74b490eeef..3a2ad0b66b 100644 --- a/keystone/common/utils.py +++ b/keystone/common/utils.py @@ -39,6 +39,7 @@ config.register_int('crypt_strength', default=40000) ISO_TIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ' +MAX_PASSWORD_LENGTH = 4096 def import_class(import_str): @@ -189,9 +190,17 @@ class Ec2Signer(object): return b64 +def trunc_password(password): + """Truncate passwords to the MAX_PASSWORD_LENGTH.""" + if len(password) > MAX_PASSWORD_LENGTH: + return password[:MAX_PASSWORD_LENGTH] + else: + return password + + def hash_password(password): """Hash a password. Hard.""" - password_utf8 = password.encode('utf-8') + password_utf8 = trunc_password(password).encode('utf-8') if passlib.hash.sha512_crypt.identify(password_utf8): return password_utf8 h = passlib.hash.sha512_crypt.encrypt(password_utf8, @@ -201,7 +210,7 @@ def hash_password(password): def ldap_hash_password(password): """Hash a password. Hard.""" - password_utf8 = password.encode('utf-8') + password_utf8 = trunc_password(password).encode('utf-8') h = passlib.hash.ldap_salted_sha1.encrypt(password_utf8) return h @@ -209,7 +218,7 @@ def ldap_hash_password(password): def ldap_check_password(password, hashed): if password is None: return False - password_utf8 = password.encode('utf-8') + password_utf8 = trunc_password(password).encode('utf-8') h = passlib.hash.ldap_salted_sha1.encrypt(password_utf8) return passlib.hash.ldap_salted_sha1.verify(password_utf8, hashed) @@ -223,7 +232,7 @@ def check_password(password, hashed): """ if password is None: return False - password_utf8 = password.encode('utf-8') + password_utf8 = trunc_password(password).encode('utf-8') return passlib.hash.sha512_crypt.verify(password_utf8, hashed) diff --git a/tests/test_utils.py b/tests/test_utils.py index b551b815a8..52efafcb91 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -43,6 +43,11 @@ class UtilsTestCase(test.TestCase): self.assertTrue(utils.check_password(password, hashed)) self.assertFalse(utils.check_password(wrong, hashed)) + def test_hash_long_password(self): + bigboy = '0' * 9999999 + hashed = utils.hash_password(bigboy) + self.assertTrue(utils.check_password(bigboy, hashed)) + def test_hash_edge_cases(self): hashed = utils.hash_password('secret') self.assertFalse(utils.check_password('', hashed))