diff --git a/app/ldap_client.py b/app/ldap_client.py new file mode 100644 index 0000000..976c67a --- /dev/null +++ b/app/ldap_client.py @@ -0,0 +1,60 @@ +import ldap3 +from typing import Tuple + +class Client(): + def __init__(self, address: str, port: int, base_dn: str, primary_attribute: str = "uid", tls: bool = False): + self.server = ldap3.Server(host=address, port=port, use_ssl=tls) + self.base_dn = base_dn + self.address = address + self.port = port + self.tls = tls + self.primary_attribute = primary_attribute + + def bind(self, user: str, bind_passwd: str) -> Tuple[bool, str]: + user_dn = f"{self.primary_attribute}={user},{self.base_dn}" + + self.link = ldap3.Connection(self.server, user=user_dn, password=bind_passwd) + + try: + status = self.link.bind() + except Exception as _: + status = False + + if status == False: + print(f"[!!] Could not bind {user_dn} to the LDAP directory: {self.link.last_error}") + return (status, "") + + return (status, user_dn) + + def unbind(self) -> bool: + if self.link.bound != True: + return False + + try: + self.link.unbind() + except Exception as e: + pass + + return True + + def change_pwd(self, user_dn: str, new_password: str) -> bool: + if self.link.bound == False: + print("[!!] Can't change the password: not bound to the server") + return False + + status = self.link.modify(user_dn, {'userPassword': [(ldap3.MODIFY_REPLACE, [new_password])]}) + if status == True: + print(f"[++] Changed password of user {user_dn}") + else: + print(f"[!!] Could not change password of user {user_dn}: {self.link.last_error}") + + return status + +if __name__ == "__main__": + client = Client("dc01.lan.alxczl.fr", 636, "cn=users,cn=accounts,dc=lan,dc=alxczl,dc=fr", True) + client_dn = "uid=alexandre,cn=users,cn=accounts,dc=lan,dc=alxczl,dc=fr" + res = client.bind(client_dn, "Getshrektm8") + if res[0] == False: + print(client.link.result["description"]) + + #client.link.unbind() \ No newline at end of file diff --git a/app/reset.py b/app/reset.py index 4d3827d..f6036fd 100644 --- a/app/reset.py +++ b/app/reset.py @@ -1,15 +1,18 @@ -import functools +from . import ldap_client from flask import ( - Blueprint, flash, g, redirect, render_template, request, session, url_for + Blueprint, render_template, flash, + current_app ) from flask_wtf import FlaskForm -from wtforms import StringField, PasswordField, BooleanField, \ +from wtforms import ( + StringField, PasswordField, SubmitField -from wtforms.validators import ValidationError, DataRequired, \ - Email, EqualTo, Length, Regexp -from werkzeug.security import check_password_hash, generate_password_hash -import re +) +from wtforms.validators import ( + ValidationError, DataRequired, + EqualTo, Length, Regexp +) bp = Blueprint('reset', __name__, url_prefix='/reset') @@ -49,11 +52,21 @@ class ResetPasswordForm(FlaskForm): for char in self.username.data: if char in excluded_chars: raise ValidationError( - f"Character {char} is not allowed in a login.") + f"Character {char} is not allowed in an username.") @bp.route('/', methods=('GET', 'POST')) def reset(): form = ResetPasswordForm() if form.validate_on_submit(): - return f'''

Welcome {form.username.data}

''' + client = ldap_client.Client(address=current_app.config["LDAP_ADDR"], port=current_app.config["LDAP_PORT"], base_dn=current_app.config["BASE_DN"], tls=current_app.config["LDAP_TLS"]) + bind_status = client.bind(form.username._value(), form.currentpassword._value()) + if bind_status[0] == False: + flash(f"Connection failed, are you sure that your login and password are correct ? ({client.link.last_error})") + elif client.change_pwd(bind_status[1], form.newpassword._value()) == False: + flash(f"An error occured and your password was not changed, sorry. ({client.link.last_error})") + client.unbind() + else: + flash('Your password has been changed !') + client.unbind() + return render_template('reset.html', form=form) \ No newline at end of file