Add a utils function to test crypt salts

This commit is contained in:
Valentin Samir 2016-07-01 01:10:33 +02:00
parent a5ed74ee56
commit 95511943e8
2 changed files with 34 additions and 5 deletions

View File

@ -181,3 +181,11 @@ class UtilsTestCase(TestCase):
url3 = utils.update_url(u"https://www.example.com?toto=1", {u"toto": u"2"}) url3 = utils.update_url(u"https://www.example.com?toto=1", {u"toto": u"2"})
self.assertEqual(url3, u"https://www.example.com?toto=2") self.assertEqual(url3, u"https://www.example.com?toto=2")
def test_crypt_salt_is_valid(self):
"""test the function crypt_salt_is_valid who test if a crypt salt is valid"""
self.assertFalse(utils.crypt_salt_is_valid("")) # len 0
self.assertFalse(utils.crypt_salt_is_valid("a")) # len 1
self.assertFalse(utils.crypt_salt_is_valid("$$")) # start with $ followed by $
self.assertFalse(utils.crypt_salt_is_valid("$toto")) # start with $ but no secondary $
self.assertFalse(utils.crypt_salt_is_valid("$toto$toto")) # algorithm toto not known

View File

@ -89,7 +89,7 @@ def update_url(url, params):
query = list(query.items()) query = list(query.items())
query.sort() query.sort()
url_query = urlencode(query) url_query = urlencode(query)
if not isinstance(url_query, bytes): if not isinstance(url_query, bytes): # pragma: no cover in python3 urlencode return an unicode
url_query = url_query.encode("utf-8") url_query = url_query.encode("utf-8")
url_parts[4] = url_query url_parts[4] = url_query
return urlunparse(url_parts).decode('utf-8') return urlunparse(url_parts).decode('utf-8')
@ -152,6 +152,27 @@ def gen_saml_id():
return _gen_ticket('_') return _gen_ticket('_')
def crypt_salt_is_valid(salt):
"""Return True is salt is valid has a crypt salt, False otherwise"""
if len(salt) < 2:
return False
else:
if salt[0] == '$':
if salt[1] == '$':
return False
else:
if '$' not in salt[1:]:
return False
else:
hashed = crypt.crypt("", salt)
if not hashed or '$' not in hashed[1:]:
return False
else:
return True
else:
return True
class LdapHashUserPassword(object): class LdapHashUserPassword(object):
"""Please see https://tools.ietf.org/id/draft-stroeder-hashed-userpassword-values-01.html""" """Please see https://tools.ietf.org/id/draft-stroeder-hashed-userpassword-values-01.html"""
@ -252,9 +273,9 @@ class LdapHashUserPassword(object):
if six.PY3: if six.PY3:
password = password.decode(charset) password = password.decode(charset)
salt = salt.decode(charset) salt = salt.decode(charset)
hashed_password = crypt.crypt(password, salt) if not crypt_salt_is_valid(salt):
if hashed_password is None:
raise cls.BadSalt("System crypt implementation do not support the salt %r" % salt) raise cls.BadSalt("System crypt implementation do not support the salt %r" % salt)
hashed_password = crypt.crypt(password, salt)
if six.PY3: if six.PY3:
hashed_password = hashed_password.encode(charset) hashed_password = hashed_password.encode(charset)
return scheme + hashed_password return scheme + hashed_password
@ -306,9 +327,9 @@ def check_password(method, password, hashed_password, charset):
password = password.decode(charset) password = password.decode(charset)
salt = salt.decode(charset) salt = salt.decode(charset)
hashed_password = hashed_password.decode(charset) hashed_password = hashed_password.decode(charset)
crypted_password = crypt.crypt(password, salt) if not crypt_salt_is_valid(salt):
if crypted_password is None:
raise ValueError("System crypt implementation do not support the salt %r" % salt) raise ValueError("System crypt implementation do not support the salt %r" % salt)
crypted_password = crypt.crypt(password, salt)
return crypted_password == hashed_password return crypted_password == hashed_password
elif method == "ldap": elif method == "ldap":
scheme = LdapHashUserPassword.get_scheme(hashed_password) scheme = LdapHashUserPassword.get_scheme(hashed_password)