#11 passwords are now stored with aes-128 encryption

This commit is contained in:
Uwe Kamper 2013-10-27 21:13:41 +01:00
parent 6bc87b605c
commit 5e29478516
6 changed files with 103 additions and 18 deletions

View file

@ -5,6 +5,7 @@ import ldap
import copy
from django.conf import settings
from password_encryption import get_ldap_password
"""
Example configuration:
@ -14,8 +15,11 @@ CBASE_BASE_DN = 'ou=crew,dc=c-base,dc=org'
"""
def retrieve_member(request):
# TODO: Put password in encrypted session storage
return MemberValues(request.user.username, request.session['ldap_password'])
ldap_password = get_ldap_password(request)
session = dict(request.session)
print "session:", session
print "cookies:", request.COOKIES
return MemberValues(request.user.username, ldap_password)
class MemberValues(object):
@ -80,7 +84,8 @@ class MemberValues(object):
print "modattrs: ",mod_attrs
result = l.modify_s(dn, mod_attrs)
print "result is: ", result
#
# print "result is: ", result
l.unbind_s()
def change_password(self, new_password):

View file

@ -10,7 +10,8 @@ from django.utils.translation import ugettext as _
class LoginForm(forms.Form):
username = forms.CharField(max_length=255)
password = forms.CharField(max_length=255, widget=forms.PasswordInput)
password = forms.CharField(max_length=255, widget=forms.PasswordInput,
help_text=_('Cookies must be enabled.'))
def clean(self):
username = self.cleaned_data.get('username')

View file

@ -0,0 +1,64 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import base64
from Crypto import Random
from Crypto.Cipher import AES
ENCRYPTED_LDAP_PASSWORD = 'encrypted_ldap_password'
def encrypt_ldap_password(cleartext_pw):
"""
Encrypts the cleartext_pw with a randomly generated key.
Returns the key and the encrypted message containing the password.
The key is supposed to be stored into the 'session_key' cookie field we can
later use it to decrypt the password and connect to the LDAP server with it.
"""
# 16 bytes of key => AES-128
random = Random.new()
key = random.read(16)
# initialization vector
iv = random.read(16)
# do the encryption
aes = AES.new(key, AES.MODE_CFB, iv)
message = iv + aes.encrypt(cleartext_pw)
return base64.b64encode(message), base64.b64encode(key)
def decrypt_ldap_password(message, key):
"""
Takes an encrypted, base64 encoded password and the base64 encoded key.
Returns the cleartext password.
"""
decoded_message = base64.b64decode(message)
decoded_key = base64.b64decode(key)
# first 16 bytes of the message are the initialization vector
iv = decoded_message[:16]
# the rest is the encrypted password
ciphertext = decoded_message[16:]
# decrypt it
aes = AES.new(decoded_key, AES.MODE_CFB, iv)
cleartext_pw = aes.decrypt(ciphertext)
return cleartext_pw
def store_ldap_password(request, password):
"""
Stores the password in an encrypted session storage and returns the key.
"""
encrypted_pw, key = encrypt_ldap_password(password)
request.session[ENCRYPTED_LDAP_PASSWORD] = encrypted_pw
request.session.save()
return key
def get_ldap_password(request):
cookies = request.COOKIES
key = cookies.get('sessionkey', None)
if not key:
raise Exception('sessionkey not found in cookies.')
return decrypt_ldap_password(request.session[ENCRYPTED_LDAP_PASSWORD], key)

View file

@ -6,11 +6,24 @@ Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
from account.views import encrypt_ldap_password, decrypt_ldap_password
class CbmiTest(TestCase):
"""
Test for the cbmi apps.
"""
TEST_LDAP_PASSWD = 'correcthorsebatterystaple'
def encrypt_it(self):
return encrypt_ldap_password(self.TEST_LDAP_PASSWD)
def test_encrypt_ldap_password(self):
message, key = self.encrypt_it()
print 'key:', key
print 'message:', message
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)
def test_decrypt_ldap_password(self):
message, key = self.encrypt_it()
decrypted = decrypt_ldap_password(message, key)
self.assertEqual(self.TEST_LDAP_PASSWD, decrypted)

View file

@ -5,6 +5,7 @@ import os
import base64
import hashlib
from django.conf import settings
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
@ -20,6 +21,7 @@ from django.utils.translation import ugettext as _
from forms import GastroPinForm, WlanPresenceForm, LoginForm, PasswordForm, \
RFIDForm, NRF24Form, SIPPinForm, CLabPinForm, AdminForm
from cbase_members import retrieve_member
from password_encryption import *
def landingpage(request):
if request.user.is_authenticated():
@ -36,8 +38,6 @@ def landingpage(request):
except:
admins = []
# values = get_user_values(request.user.username, request.session['ldap_password'])
#return render_to_response("dashboard.html", locals())
return render(request, 'base.html', {'form': form, 'admins': admins})
def auth_login(request):
@ -57,11 +57,9 @@ def auth_login(request):
member.save()
# save password in the session for later use with LDAP
request.session['ldap_password'] = password
# TODO: Change the
key = store_ldap_password(request, password)
response = HttpResponseRedirect(redirect_to)
response.set_cookie('sessionkey', 'bla')
response.set_cookie('sessionkey', key)
return response
else:
return render(request, 'login.html', {'form': form})
@ -79,6 +77,7 @@ def home(request):
@login_required
def auth_logout(request):
request.session.pop(ENCRYPTED_LDAP_PASSWORD)
redirect_to = request.GET.get('next', '') or '/'
logout(request)
response = HttpResponseRedirect(redirect_to)
@ -154,6 +153,7 @@ def clabpin(request):
@login_required
def password(request):
"""
View that changes the password on the LDAP server.
"""
member = retrieve_member(request)
@ -163,12 +163,13 @@ def password(request):
if form.is_valid():
new_password = form.cleaned_data['password1']
member.change_password(new_password)
request.session['ldap_password'] = new_password
key = store_ldap_password(request, new_password)
request.session.save()
new_form = PasswordForm()
return render(request, 'password.html',
response = render(request, 'password.html',
{'message': _('Your password was changed. Thank you!'),
'form': new_form, 'member': member.to_dict()})
response.set_cookie('sessionkey', key)
else:
return render(request, 'password.html',
{'form': form, 'member': member.to_dict()})

View file

@ -3,3 +3,4 @@ MySQL-python==1.2.4
django-auth-ldap==1.1.4
django-json-rpc==0.6.1
django-crispy-forms==1.4.0
pycrypto==2.6.1