Skip to content
Snippets Groups Projects
Commit b889f0fa authored by Christian Dresen's avatar Christian Dresen
Browse files

Warpauth

Finished Password-Reset Function
parent 643a1a74
No related branches found
No related tags found
No related merge requests found
Showing
with 124 additions and 67 deletions
from django.contrib import admin from django.contrib import admin
# Register your models here. # Register your models here.
from warpauth.models import PasswordResetToken, LdapUser
@admin.register(PasswordResetToken)
class PasswordResetTokenAdmin(admin.ModelAdmin):
pass
@admin.register(LdapUser)
class LdapUserAdmin(admin.ModelAdmin):
pass
\ No newline at end of file
import ldap
from warpzone import settings
#
# LDAP Connector Class
# All direct LDAP Operations must use this class
# For LDAP User search please use LDAPDB instead
#
# ToDo: Escape input parameter for prevent LDAP Injection
# ToDo: Implement Singleton Design Pattern
#
class LDAPConnector:
def __init__(self):
self.__ldap_object = ldap.initialize(settings.AUTH_LDAP_SERVER_URI)
self.__ldap_object.bind_s(settings.AUTH_LDAP_BIND_DN, settings.AUTH_LDAP_BIND_PASSWORD)
def get_ldap_object(self):
return self.__ldap_object
def change_user_password(self, user, old_pw, new_pw, reset_pw=False):
try:
if old_pw is not None or reset_pw:
self.__ldap_object.passwd_s(user, old_pw, new_pw)
return 1
except ldap.UNWILLING_TO_PERFORM as e:
error = str(e)
if 'unwilling to verify old password' in error or 'old password value is empty' in error:
return -1
else:
print (e)
return -2
from django.db import models from django.db import models
from ldapdb.models.fields import CharField, IntegerField, ListField from ldapdb.models.fields import CharField, IntegerField, ListField
import ldapdb.models import ldapdb.models
from django.forms import ModelForm, HiddenInput
from django import forms
from django.utils import timezone
class PasswordResetToken(models.Model): class PasswordResetToken(models.Model):
user = models.CharField(max_length=100) user = models.CharField(max_length=100)
...@@ -20,7 +18,6 @@ class LdapUser(ldapdb.models.Model): ...@@ -20,7 +18,6 @@ class LdapUser(ldapdb.models.Model):
uid = CharField(db_column='uid', unique=True, primary_key=True) uid = CharField(db_column='uid', unique=True, primary_key=True)
email = CharField(db_column='description', max_length=200) email = CharField(db_column='description', max_length=200)
password = CharField(db_column='Password')
def __str__(self): def __str__(self):
return self.uid return self.uid
......
...@@ -3,8 +3,9 @@ ...@@ -3,8 +3,9 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<h2>{{ body_text }}</h2> <h2>{{ body_text }}</h2>
<p class="lead">{% trans "Welcome to Warpzone internal" %}</p><p /> <p class="lead">{% trans "Welcome to Warpzone internal" %}</p>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
</p>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<h2 class="form-signin-heading">{% trans "Please sign in" %}</h2> <h2 class="form-signin-heading">{% trans "Please sign in" %}</h2>
<label for="inputUser">{% trans "Username" %}</label> <label for="inputUser">{% trans "Username" %}</label>
<input name="username" type="user" id="inputUser" class="form-control" placeholder="{% trans "Username" %}" required autofocus> <input name="username" type="user" id="inputUser" class="form-control" placeholder="{% trans "Username" %}" required autofocus>
Hallo
<label for="inputPassword" style="padding-top:10px;">{% trans "Password" %}</label> <label for="inputPassword" style="padding-top:10px;">{% trans "Password" %}</label>
<input name="password" type="password" id="inputPassword" class="form-control" placeholder="{% trans "Password" %}" required> <input name="password" type="password" id="inputPassword" class="form-control" placeholder="{% trans "Password" %}" required>
{% if fail == True %} {% if fail == True %}
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<h2>{{ body_text }}</h2>
<p class="lead">{% trans "Profile Settings" %}</p><p /> <p class="lead">{% trans "Profile Settings" %}</p><p></p>
<div> <div>
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
<div> <div>
<br /> <br />
{% if error %}
<div class="alert alert-danger">{{ error }}</div><br>
{% endif %}
<form class="form-horizontal" method="POST" action="/profile/change_password/" role="form"> <form class="form-horizontal" method="POST" action="/profile/change_password/" role="form">
{% csrf_token %} {% csrf_token %}
<div class="form-group"> <div class="form-group">
......
...@@ -5,7 +5,11 @@ ...@@ -5,7 +5,11 @@
{% if token_error %} {% if token_error %}
<h2 class="form-signin-heading">{% trans "The Token is invalid" %}</h2> <h2 class="form-signin-heading">{% trans "The Token is invalid" %}</h2>
{% elif request.POST and not form_error%} {% elif request.POST and not form_error%}
{{ request.POST }} <div class="alert alert-success">
{% trans "Your password was sucessfully changed. You will be redirected within 5 seconds. If not please click" %}
<a href="/login">{% trans "here" %}</a>
<meta refresh>
</div>
{% else %} {% else %}
<form class="form" style="max-width: 330px; margin: 0 auto; padding: 40px"> <form class="form" style="max-width: 330px; margin: 0 auto; padding: 40px">
{% csrf_token %} {% csrf_token %}
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
{% if request.POST %} {% if request.POST %}
<h2 class="form-signin-heading">{% trans "If your information were right, you've got an Email" %}</h2> <h2 class="form-signin-heading">{% trans "If your information were right, you've got an Email" %}</h2>
Token is: <a href="{{ debug }}">{{ debug }}</a>
{% else %} {% else %}
<form class="form" style="max-width: 330px; margin: 0 auto; padding: 40px"> <form class="form" style="max-width: 330px; margin: 0 auto; padding: 40px">
......
import ldap
from warpzone import settings
pages = {'pages': [ pages = {'pages': [
{"link":"pizza", "name": "PizzaSheet"}, {"link": "pizza", "name": "PizzaSheet"},
{"link":"about", "name": "About"}, {"link": "about", "name": "About"},
]} ]}
def __init_ldap():
ldapObject = ldap.initialize(settings.AUTH_LDAP_SERVER_URI)
ldapObject.bind_s(settings.AUTH_LDAP_BIND_DN, settings.AUTH_LDAP_BIND_PASSWORD)
return ldapObject
def ldap_change_password(user,old_pw, new_pw):
ldapObject = __init_ldap()
try:
ldapObject.passwd_s(user,old_pw,new_pw)
return 1
except ldap.UNWILLING_TO_PERFORM as e:
if 'unwilling to verify old password' in e:
return -1
return 0
...@@ -7,7 +7,7 @@ from django.contrib.auth.decorators import login_required ...@@ -7,7 +7,7 @@ from django.contrib.auth.decorators import login_required
from warpauth.util import * from warpauth.util import *
def login_view(request): def login_view(request):
pages['body'] = "login" pages['page_title'] = "Login"
pages['body_text'] = "Login" pages['body_text'] = "Login"
pages['fail'] = False pages['fail'] = False
......
...@@ -2,26 +2,40 @@ from django.shortcuts import render ...@@ -2,26 +2,40 @@ from django.shortcuts import render
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, HttpResponseNotFound from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, HttpResponseNotFound
from django.shortcuts import redirect from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from warpauth.ldap_connector import LDAPConnector
from warpauth.models import LdapUser from warpauth.models import LdapUser
from warpauth.util import * from warpauth.util import *
## ##
# http://www.python-ldap.org/doc/html/ldap.html#ldap.LDAPObject # http://www.python-ldap.org/doc/html/ldap.html#ldap.LDAPObject
## ##
@login_required(login_url='/login/', redirect_field_name=None) @login_required(login_url='/login/', redirect_field_name=None)
def index(request): def index(request):
print(request.user.ldap_user.group_names) pages["error"] = ""
pages["success"] = False
pages['ldap_groups'] = request.user.ldap_user.group_names pages['ldap_groups'] = request.user.ldap_user.group_names
#ldap_change_password(request.user.ldap_user.dn,"123456","12345")
return HttpResponse(render(request, 'warpauth/profile.html', pages)) return HttpResponse(render(request, 'warpauth/profile.html', pages))
@login_required(login_url='/login/', redirect_field_name=None) @login_required(login_url='/login/', redirect_field_name=None)
def change_password(request): def change_password(request):
pages["error"] = ""
pages["success"] = False
if request.method != 'POST': if request.method != 'POST':
redirect("/") redirect("/")
print(request.POST)
return HttpResponse(render(request, 'warpauth/profile.html', pages)) if "old_pw" not in request.POST or "new_pw" not in request.POST or "new_pw_confirm" not in request.POST:
\ No newline at end of file pages["error"] = "Please fill in all fields"
elif request.POST["new_pw"] != request.POST["new_pw_confirm"]:
pages["error"] = "Password confirmation did not match"
else:
ldap_connector = LDAPConnector()
ret = ldap_connector.change_password(request.user.ldap_user.dn, request.POST["old_pw"], request.POST["new_pw"])
if ret == -1:
pages["error"] = "Old password did not match"
else:
pages["success"] = True
return HttpResponse(render(request, 'warpauth/profile.html', pages))
from django.shortcuts import render import os
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, HttpResponseNotFound
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import cache_page
from warpauth.util import *
from warpauth.models import PasswordResetToken, LdapUser
import hashlib import hashlib
import logging import logging
import os
import datetime import datetime
from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.http import HttpResponse
from django.shortcuts import render
from warpauth.ldap_connector import LDAPConnector
from warpauth.util import *
from warpauth.models import PasswordResetToken, LdapUser
from warpzone.settings import PW_RESET_TOKEN_LIFETIME
#
# Function to generate a password reset Token
# ToDo: Implement Email with Token
# ToDo: Remove Debug outputs
#
def gen_token(request): def gen_token(request):
logger = logging.getLogger("reset_password") logger = logging.getLogger("reset_password")
...@@ -20,44 +26,53 @@ def gen_token(request): ...@@ -20,44 +26,53 @@ def gen_token(request):
usr = LdapUser.objects.get(uid=request.POST["username"]) usr = LdapUser.objects.get(uid=request.POST["username"])
if usr.email == request.POST["email"]: if usr.email == request.POST["email"]:
p = PasswordResetToken() p = PasswordResetToken()
p.user=usr.uid p.user = usr.uid
p.email=usr.email p.email = usr.email
p.hash = hashlib.sha1(os.urandom(128)).hexdigest() p.hash = hashlib.sha1(os.urandom(128)).hexdigest()
p.save() p.save()
pages["debug"] = "http://localhost/reset_password/%s" % p.hash
logger.info("Success for %s", usr.uid) logger.info("Success for %s", usr.uid)
except Exception as e: except Exception as e:
print(e) print(e)
logger.error("Failed for %s with %s", request.POST["username"],e) logger.error("Failed for %s with %s", request.POST["username"], e)
else: else:
pass pass
return HttpResponse(render(request, 'warpauth/reset_password/token_gen.html', pages)) return HttpResponse(render(request, 'warpauth/reset_password/token_gen.html', pages))
#
# Function to change user password with a reset Token
# ToDo: Implement Email after password change
# ToDo: Implement automatic redirection if succeeded in template
#
def change_password(request, reset_hash=None): def change_password(request, reset_hash=None):
logger = logging.getLogger("reset_password") # logger = logging.getLogger("reset_password")
# Debug # Debug
for pw in PasswordResetToken.objects.all(): for pw in PasswordResetToken.objects.all():
print (pw.hash) print(pw.hash)
# #
try: try:
passwordHash = PasswordResetToken.objects.get(hash=reset_hash) pw_reset_token = PasswordResetToken.objects.get(hash=reset_hash)
timediff = datetime.datetime.now() - passwordHash.created time_difference = datetime.datetime.now() - pw_reset_token.created
if timediff.seconds/60 > 5: if time_difference.seconds/60 > PW_RESET_TOKEN_LIFETIME:
# passwordHash.delete() pw_reset_token.delete()
raise ValidationError("Token not valid") raise ValidationError("Token not valid")
if request.POST: if request.POST:
if request.POST["password"] != request.POST["password2"]: if request.POST["password"] != request.POST["password2"] or request.POST["password"] == "":
pages["form_error"] = True pages["form_error"] = True
else: else:
pass user = LdapUser.objects.get(uid=pw_reset_token.user)
ldap_connector = LDAPConnector()
ldap_connector.change_user_password(user.build_dn(), None, request.POST["password"], True)
pw_reset_token.delete()
else: else:
pages["username"] = passwordHash.user pages["username"] = pw_reset_token.user
except (ObjectDoesNotExist, ValidationError) as e: except (ObjectDoesNotExist, ValidationError) as e:
print(e)
pages["token_error"] = True pages["token_error"] = True
except Exception as e: except Exception as e:
print(e) print(e)
return HttpResponse(render(request, 'warpauth/reset_password/change_password.html', pages)) return HttpResponse(render(request, 'warpauth/reset_password/change_password.html', pages))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment