#11 passwords are now stored with aes-128 encryption
This commit is contained in:
parent
6bc87b605c
commit
5e29478516
6 changed files with 103 additions and 18 deletions
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
64
account/password_encryption.py
Normal file
64
account/password_encryption.py
Normal 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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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()})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue