From 2bdaf32e87b5316c9943fc59378fb67c5d46b155 Mon Sep 17 00:00:00 2001 From: Nikolai Kristiansen Date: Mon, 17 Oct 2011 01:57:28 +0200 Subject: [PATCH] Experimental password changing with builtins. --- main/forms.py | 32 +++++++++++++++++++++++++++----- main/models.py | 23 ++++++++++++++++++----- main/passwd.py | 10 +++++----- main/validators.py | 6 ++++++ templates/public/index.html | 2 +- 5 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 main/validators.py diff --git a/main/forms.py b/main/forms.py index f04a697..05f770c 100644 --- a/main/forms.py +++ b/main/forms.py @@ -1,8 +1,30 @@ -from django.contrib.auth.forms import PasswordChangeForm, SetPasswordForm -class LDAPPasswordChangeForm(PasswordChangeForm): - # TODO: Change password here - pass +from django.contrib.auth.forms import SetPasswordForm +from models import * + +# not needed? class LDAPSetPasswordForm(SetPasswordForm): - # TODO: Set password here + def save(self, commit=True): + # Lookup the Ldap user with the identical username (1-to-1). + self.user = LdapUser.objects.get(username=self.user.username) + + self.user.set_password(self.cleaned_data['new_password1']) + if commit: + self.user.save() + return self.user + +class LDAPPasswordChangeForm(LDAPSetPasswordForm): pass + #old_password = forms.CharField(label=_("Old password"), widget=forms.PasswordInput) + + #def clean_old_password(self): + # """ + # Validates that the old_password field is correct. + # """ + # old_password = self.cleaned_data["old_password"] + # if not self.user.check_password(old_password): + # raise forms.ValidationError(_("Your old password was entered incorrectly. Please enter it again.")) + # return old_password + # + #PasswordChangeForm.base_fields.keyOrder = ['old_password', 'new_password1', 'new_password2'] + diff --git a/main/models.py b/main/models.py index 83745fc..b20fb7d 100644 --- a/main/models.py +++ b/main/models.py @@ -1,6 +1,8 @@ from ldapdb.models.fields import CharField, ImageField, IntegerField, ListField import ldapdb.models - +import passwd +from django.core.validators import MinLengthValidator +from validators import PasswordValidator class LdapUser(ldapdb.models.Model): """ Class for representing an LDAP user entry. @@ -27,10 +29,21 @@ class LdapUser(ldapdb.models.Model): username = CharField(db_column='uid', primary_key=True) password = CharField(db_column='userPassword') - def set_new_password(self, new_pw): - import passwd - self.password = passwd.ldap_create(new_pw) - self.save() + def set_password(self, raw_password): + if raw_password is None: + self.password = "!" + else: + # Validation here? + MinLengthValidator(8)(raw_password) + PasswordValidator(raw_password) + self.password = passwd.ldap_create(raw_password) + self.save() + + def check_password(self, raw_password): + """ + Returns a boolean of whether the raw_password was correct. + """ + return passwd.ldap_validate(raw_password, self.password) def __str__(self): return self.username diff --git a/main/passwd.py b/main/passwd.py index 6fd6cff..8287416 100644 --- a/main/passwd.py +++ b/main/passwd.py @@ -7,19 +7,19 @@ from base64 import decodestring as decode # - http://www.openldap.org/faq/data/cache/347.html # - http://www.openldap.org/doc/admin24/security.html -def ldap_create(password, hash_type='ssha'): +def ldap_create(raw_password, hash_type='ssha'): # Generate a salted SHA hash salt = os.urandom(4) - h = hashlib.sha1(password) + h = hashlib.sha1(raw_password) h.update(salt) return "{SSHA}" + encode(h.digest() + salt)[:-1] -def ldap_validate(challenge_password, password): +def ldap_validate(raw_password, challenge_password): # challenge_password is hash from db - # password is the cleartext password. + # raw_password is the cleartext password. challenge_bytes = decode(challenge_password[6:]) digest = challenge_bytes[:20] salt = challenge_bytes[20:] - hr = hashlib.sha1(password) + hr = hashlib.sha1(raw_password) hr.update(salt) return digest == hr.digest() diff --git a/main/validators.py b/main/validators.py new file mode 100644 index 0000000..dcdc6c0 --- /dev/null +++ b/main/validators.py @@ -0,0 +1,6 @@ +from django.core.validators import RegexValidator +import re + +# Passwords should not contain " +password_re = re.compile(r'(?{{request.user}}s profile +{{user}}s profile Forgot password? {% endblock %}