98 lines
3.4 KiB
Python
98 lines
3.4 KiB
Python
# Copyright The IETF Trust 2007, All Rights Reserved
|
|
|
|
from django.contrib.auth.backends import ModelBackend
|
|
from django.forms.fields import email_re
|
|
from django.contrib.auth.models import User
|
|
from django.conf import settings
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from ietf.ietfauth.models import UserMap
|
|
import md5
|
|
|
|
def compat_check_password(user, raw_password):
|
|
"""
|
|
Returns a boolean of whether the raw_password was correct. Handles
|
|
crypt and htdigest formats, and updates the password to htdigest
|
|
on first use. This is like User.check_password().
|
|
"""
|
|
enc_password = user.password
|
|
algo, salt, hsh = enc_password.split('$')
|
|
if algo == 'crypt':
|
|
import crypt
|
|
is_correct = ( salt + hsh == crypt.crypt(raw_password, salt) )
|
|
if is_correct:
|
|
# upgrade to htdigest
|
|
set_password(user, raw_password)
|
|
return is_correct
|
|
if algo == 'htdigest':
|
|
# Check username hash.
|
|
is_correct = ( hsh == htdigest( user.username, raw_password ) )
|
|
if not is_correct:
|
|
# Try to check email hash, which we stored in the profile.
|
|
# If the profile doesn't exist, that's odd but we shouldn't
|
|
# completely fail, so try/except it.
|
|
try:
|
|
is_correct = ( user.get_profile().email_htdigest == htdigest( user.email, raw_password ) )
|
|
except ObjectDoesNotExist:
|
|
# no user profile to store the htdigest, so can't check it.
|
|
pass
|
|
return is_correct
|
|
# permit django passwords, but upgrade to htdigest
|
|
is_correct = user.check_password(raw_password)
|
|
if is_correct:
|
|
# upgrade to htdigest
|
|
set_password(user, raw_password)
|
|
return is_correct
|
|
|
|
# Based on http://www.djangosnippets.org/snippets/74/
|
|
# but modified to use compat_check_password for all users.
|
|
class EmailBackend(ModelBackend):
|
|
def authenticate(self, username=None, password=None):
|
|
try:
|
|
if email_re.search(username):
|
|
user = User.objects.get(email__iexact=username)
|
|
else:
|
|
user = User.objects.get(username__iexact=username)
|
|
except User.DoesNotExist:
|
|
#
|
|
# See if there's an IETF person with this address:
|
|
try:
|
|
usermap = UserMap.objects.distinct().get(person__emailaddress__address__iexact=username)
|
|
except UserMap.DoesNotExist:
|
|
return None
|
|
except AssertionError:
|
|
# multiple UserMaps, should never happen!
|
|
return None
|
|
user = usermap.user
|
|
if compat_check_password(user, password):
|
|
return user
|
|
return None
|
|
|
|
def get_user(self, user_id):
|
|
try:
|
|
return User.objects.get(pk=user_id)
|
|
except User.DoesNotExist:
|
|
return None
|
|
|
|
def htdigest( username, password, realm=None ):
|
|
"""Returns a hashed password in the Apache htdigest format, which
|
|
is used in an AuthDigestFile ."""
|
|
if realm is None:
|
|
try:
|
|
realm = settings.DIGEST_REALM
|
|
except AttributeError:
|
|
realm = 'IETF'
|
|
return md5.md5( ':'.join( [ username, realm, password ] ) ).hexdigest()
|
|
|
|
def set_password( user, password, realm=None ):
|
|
# The username-hashed digest goes in the user database;
|
|
# the email-address-hashed digest goes in the userprof.
|
|
user.password = '$'.join( [ 'htdigest', '',
|
|
htdigest( user.username, password, realm ) ] )
|
|
user.save()
|
|
( userprof, created ) = UserMap.objects.get_or_create( user=user )
|
|
userprof.email_htdigest = htdigest( user.email, password, realm )
|
|
userprof.rfced_htdigest = htdigest( user.email, password, 'RFC Editor' )
|
|
userprof.save()
|
|
|
|
# changes done by convert-096.py:changed email_re import
|