diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index 75b3ca4ece..08488237c7 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -11,7 +11,7 @@ from django.utils.translation import ugettext, ugettext_lazy as _ from django.contrib.auth import authenticate from django.contrib.auth.models import User -from django.contrib.auth.hashers import UNUSABLE_PASSWORD, is_password_usable, identify_hasher +from django.contrib.auth.hashers import UNUSABLE_PASSWORD, identify_hasher from django.contrib.auth.tokens import default_token_generator from django.contrib.sites.models import get_current_site @@ -24,22 +24,22 @@ mask_password = lambda p: "%s%s" % (p[:UNMASKED_DIGITS_TO_SHOW], "*" * max(len(p class ReadOnlyPasswordHashWidget(forms.Widget): def render(self, name, value, attrs): encoded = value - - if not is_password_usable(encoded): - return "None" - final_attrs = self.build_attrs(attrs) - try: - hasher = identify_hasher(encoded) - except ValueError: - summary = mark_safe("Invalid password format or unknown hashing algorithm.") + if encoded == '' or encoded == UNUSABLE_PASSWORD: + summary = mark_safe("%s" % ugettext("No password set.")) else: - summary = format_html_join('', - "{0}: {1} ", - ((ugettext(key), value) - for key, value in hasher.safe_summary(encoded).items()) - ) + try: + hasher = identify_hasher(encoded) + except ValueError: + summary = mark_safe("%s" % ugettext( + "Invalid password format or unknown hashing algorithm.")) + else: + summary = format_html_join('', + "{0}: {1} ", + ((ugettext(key), value) + for key, value in hasher.safe_summary(encoded).items()) + ) return format_html("{1}", flatatt(final_attrs), summary) diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py index bd0c6778c9..c628059d34 100644 --- a/django/contrib/auth/hashers.py +++ b/django/contrib/auth/hashers.py @@ -28,7 +28,13 @@ def reset_hashers(**kwargs): def is_password_usable(encoded): - return (encoded is not None and encoded != UNUSABLE_PASSWORD) + if encoded is None or encoded == UNUSABLE_PASSWORD: + return False + try: + hasher = identify_hasher(encoded) + except ValueError: + return False + return True def check_password(password, encoded, setter=None, preferred='default'): diff --git a/django/contrib/auth/tests/forms.py b/django/contrib/auth/tests/forms.py index 594b55c633..8fee3501c5 100644 --- a/django/contrib/auth/tests/forms.py +++ b/django/contrib/auth/tests/forms.py @@ -236,23 +236,30 @@ class UserChangeFormTest(TestCase): # Just check we can create it form = MyUserForm({}) + def test_unsuable_password(self): + user = User.objects.get(username='empty_password') + user.set_unusable_password() + user.save() + form = UserChangeForm(instance=user) + self.assertIn(_("No password set."), form.as_table()) + def test_bug_17944_empty_password(self): user = User.objects.get(username='empty_password') form = UserChangeForm(instance=user) - # Just check that no error is raised. - form.as_table() + self.assertIn(_("Invalid password format or unknown hashing algorithm."), + form.as_table()) def test_bug_17944_unmanageable_password(self): user = User.objects.get(username='unmanageable_password') form = UserChangeForm(instance=user) - # Just check that no error is raised. - form.as_table() + self.assertIn(_("Invalid password format or unknown hashing algorithm."), + form.as_table()) def test_bug_17944_unknown_password_algorithm(self): user = User.objects.get(username='unknown_password') form = UserChangeForm(instance=user) - # Just check that no error is raised. - form.as_table() + self.assertIn(_("Invalid password format or unknown hashing algorithm."), + form.as_table()) @override_settings(USE_TZ=False, PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) diff --git a/django/contrib/auth/tests/hashers.py b/django/contrib/auth/tests/hashers.py index 673263b566..d867a57d98 100644 --- a/django/contrib/auth/tests/hashers.py +++ b/django/contrib/auth/tests/hashers.py @@ -100,6 +100,10 @@ class TestUtilsHashPass(unittest.TestCase): self.assertRaises(ValueError, doit) self.assertRaises(ValueError, identify_hasher, "lolcat$salt$hash") + def test_bad_encoded(self): + self.assertFalse(is_password_usable('letmein_badencoded')) + self.assertFalse(is_password_usable('')) + def test_low_level_pkbdf2(self): hasher = PBKDF2PasswordHasher() encoded = hasher.encode('letmein', 'seasalt')