Ticket #20593: empty-password-fix.patch

File empty-password-fix.patch, 6.4 KB (added by jonaskoelker, 21 months ago)

Proper fix, plus test cases

  • django/contrib/auth/hashers.py

    diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
    index 6abdb5f..a3e1511 100644
    a b def check_password(password, encoded, setter=None, preferred='default'): 
    4747    If setter is specified, it'll be called when you need to
    4848    regenerate the password.
    4949    """
    50     if not password or not is_password_usable(encoded):
     50    if not is_password_usable(encoded):
    5151        return False
    5252
    5353    preferred = get_hasher(preferred)
    def make_password(password, salt=None, hasher='default'): 
    6868    password is None or blank then UNUSABLE_PASSWORD will be
    6969    returned which disallows logins.
    7070    """
    71     if not password:
     71    if password is None:
    7272        return UNUSABLE_PASSWORD
    7373
    7474    hasher = get_hasher(hasher)
    class PBKDF2PasswordHasher(BasePasswordHasher): 
    222222    digest = hashlib.sha256
    223223
    224224    def encode(self, password, salt, iterations=None):
    225         assert password
    226225        assert salt and '$' not in salt
    227226        if not iterations:
    228227            iterations = self.iterations
    class SHA1PasswordHasher(BasePasswordHasher): 
    350349    algorithm = "sha1"
    351350
    352351    def encode(self, password, salt):
    353         assert password
    354352        assert salt and '$' not in salt
    355353        hash = hashlib.sha1(force_bytes(salt + password)).hexdigest()
    356354        return "%s$%s$%s" % (self.algorithm, salt, hash)
    class MD5PasswordHasher(BasePasswordHasher): 
    378376    algorithm = "md5"
    379377
    380378    def encode(self, password, salt):
    381         assert password
    382379        assert salt and '$' not in salt
    383380        hash = hashlib.md5(force_bytes(salt + password)).hexdigest()
    384381        return "%s$%s$%s" % (self.algorithm, salt, hash)
  • django/contrib/auth/tests/test_hashers.py

    diff --git a/django/contrib/auth/tests/test_hashers.py b/django/contrib/auth/tests/test_hashers.py
    index d49fdc4..88c8f40 100644
    a b class TestUtilsHashPass(unittest.TestCase): 
    4141        self.assertFalse(check_password('lètmeinz', encoded))
    4242        self.assertEqual(identify_hasher(encoded).algorithm, "pbkdf2_sha256")
    4343
     44        encoded = make_password('', 'sodium chloride', 'pbkdf2_sha256')
     45        self.assertTrue(is_password_usable(encoded))
     46        self.assertTrue(check_password('', encoded))
     47
    4448    def test_sha1(self):
    4549        encoded = make_password('lètmein', 'seasalt', 'sha1')
    4650        self.assertEqual(encoded,
    class TestUtilsHashPass(unittest.TestCase): 
    5054        self.assertFalse(check_password('lètmeinz', encoded))
    5155        self.assertEqual(identify_hasher(encoded).algorithm, "sha1")
    5256
     57        encoded = make_password('', 'sodium chloride', 'sha1')
     58        self.assertTrue(is_password_usable(encoded))
     59        self.assertTrue(check_password('', encoded))
     60
    5361    def test_md5(self):
    5462        encoded = make_password('lètmein', 'seasalt', 'md5')
    5563        self.assertEqual(encoded,
    class TestUtilsHashPass(unittest.TestCase): 
    5967        self.assertFalse(check_password('lètmeinz', encoded))
    6068        self.assertEqual(identify_hasher(encoded).algorithm, "md5")
    6169
     70        encoded = make_password('', 'sodium chloride', 'md5')
     71        self.assertTrue(is_password_usable(encoded))
     72        self.assertTrue(check_password('', encoded))
     73
    6274    def test_unsalted_md5(self):
    6375        encoded = make_password('lètmein', '', 'unsalted_md5')
    6476        self.assertEqual(encoded, '88a434c88cca4e900f7874cd98123f43')
    class TestUtilsHashPass(unittest.TestCase): 
    7284        self.assertTrue(check_password('lètmein', alt_encoded))
    7385        self.assertFalse(check_password('lètmeinz', alt_encoded))
    7486
     87        encoded = make_password('', '', 'unsalted_md5')
     88        self.assertTrue(is_password_usable(encoded))
     89        self.assertTrue(check_password('', encoded))
     90
    7591    def test_unsalted_sha1(self):
    7692        encoded = make_password('lètmein', '', 'unsalted_sha1')
    7793        self.assertEqual(encoded, 'sha1$$6d138ca3ae545631b3abd71a4f076ce759c5700b')
    class TestUtilsHashPass(unittest.TestCase): 
    8399        alt_encoded = encoded[6:]
    84100        self.assertFalse(check_password('lètmein', alt_encoded))
    85101
     102        encoded = make_password('', '', 'unsalted_sha1')
     103        self.assertTrue(is_password_usable(encoded))
     104        self.assertTrue(check_password('', encoded))
     105
    86106    @skipUnless(crypt, "no crypt module to generate password.")
    87107    def test_crypt(self):
    88108        encoded = make_password('lètmei', 'ab', 'crypt')
    class TestUtilsHashPass(unittest.TestCase): 
    92112        self.assertFalse(check_password('lètmeiz', encoded))
    93113        self.assertEqual(identify_hasher(encoded).algorithm, "crypt")
    94114
     115        encoded = make_password('', 'ab', 'crypt')
     116        self.assertTrue(is_password_usable(encoded))
     117        self.assertTrue(check_password('', encoded))
     118
    95119    @skipUnless(bcrypt, "bcrypt not installed")
    96120    def test_bcrypt_sha256(self):
    97121        encoded = make_password('lètmein', hasher='bcrypt_sha256')
    class TestUtilsHashPass(unittest.TestCase): 
    108132        self.assertTrue(check_password(password, encoded))
    109133        self.assertFalse(check_password(password[:72], encoded))
    110134
     135        encoded = make_password('', 'bcrypt_sha256')
     136        self.assertTrue(is_password_usable(encoded))
     137        self.assertTrue(check_password('', encoded))
     138
    111139    @skipUnless(bcrypt, "bcrypt not installed")
    112140    def test_bcrypt(self):
    113141        encoded = make_password('lètmein', hasher='bcrypt')
    class TestUtilsHashPass(unittest.TestCase): 
    117145        self.assertFalse(check_password('lètmeinz', encoded))
    118146        self.assertEqual(identify_hasher(encoded).algorithm, "bcrypt")
    119147
     148        encoded = make_password('', 'bcrypt')
     149        self.assertTrue(is_password_usable(encoded))
     150        self.assertTrue(check_password('', encoded))
     151
    120152    def test_unusable(self):
    121153        encoded = make_password(None)
    122154        self.assertFalse(is_password_usable(encoded))
    class TestUtilsHashPass(unittest.TestCase): 
    151183            'pbkdf2_sha1$10000$seasalt$oAfF6vgs95ncksAhGXOWf4Okq7o=')
    152184        self.assertTrue(hasher.verify('lètmein', encoded))
    153185
     186        encoded = hasher.encode('', 'sodium chloride')
     187        self.assertTrue(hasher.verify('', encoded))
     188
    154189    def test_upgrade(self):
    155190        self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
    156191        for algo in ('sha1', 'md5'):
Back to Top