Allow LDAP users to change their password.

fixes #440
This commit is contained in:
Antoine Nguyen
2013-07-08 21:17:35 +02:00
parent 50f0014f78
commit 54f6d77bcd
2 changed files with 44 additions and 26 deletions
+38 -26
View File
@@ -36,24 +36,29 @@ Extracted from `this blog
import sys
import ldap
import re
import base64, hashlib, string, crypt
import base64
import hashlib
import string
import crypt
from random import Random
from django.conf import settings
from modoboa.lib import parameters
class LDAPException(Exception): pass
class LDAPException(Exception):
pass
class LDAPAuthBackend(object):
def __init__(self):
self.server_uri = self._setting("AUTH_LDAP_SERVER_URI", "ldap://localhost")
self.user_base = self._setting("LDAP_USER_BASE", "")
self.user_filter = self._setting("LDAP_USER_FILTER", "")
self.bind_dn = self._setting("AUTH_LDAP_BIND_DN", "")
self.bind_pwd = self._setting("AUTH_LDAP_BIND_PASSWORD", "")
self.server_uri = self._setting(
"AUTH_LDAP_SERVER_URI", "ldap://localhost"
)
self.pwd_attr = self._setting("LDAP_PASSWORD_ATTR", "userPassword")
self.ldap_ad = self._setting("LDAP_ACTIVE_DIRECTORY", False)
self.conn = self._get_conn(self.bind_dn, self.bind_pwd)
self.conn = None
self.user_filter = self._setting("LDAP_USER_FILTER", "")
self.user_dn = None
def _setting(self, name, default):
try:
@@ -62,31 +67,41 @@ class LDAPAuthBackend(object):
value = default
return value
def _get_conn(self, bind_dn, bind_pwd):
def _get_conn(self, dn, password):
conn = ldap.initialize(self.server_uri)
conn.set_option(ldap.OPT_X_TLS_DEMAND, True)
conn.set_option(ldap.OPT_DEBUG_LEVEL, 255)
conn.simple_bind_s(bind_dn, bind_pwd)
conn.set_option(ldap.OPT_X_TLS_DEMAND, True)
conn.set_option(ldap.OPT_DEBUG_LEVEL, 255)
conn.simple_bind_s(dn, password)
return conn
def _expand_filter(self, rawvalue, **kwargs):
return rawvalue % kwargs
def connect_to_server(self, user, password):
if parameters.get_admin("LDAP_AUTH_METHOD", app="admin") == "searchbind":
bind_dn = self._setting("AUTH_LDAP_BIND_DN", "")
bind_pwd = self._setting("AUTH_LDAP_BIND_PASSWORD", "")
self.conn = self._get_conn(bind_dn, bind_pwd)
self.user_dn = self._find_user_dn(user)
else:
tpl = self._setting("AUTH_LDAP_USER_DN_TEMPLATE", "")
self.user_dn = tpl % {"user": user}
self.conn = self._get_conn(self.user_dn, password)
def _find_user_dn(self, user):
filtr = self._expand_filter(self.user_filter, user=user)
res = self.conn.search_s(self.user_base, ldap.SCOPE_SUBTREE, filtr)
sbase = parameters.get_admin("LDAP_SEARCH_BASE", app="admin")
sfilter = parameters.get_admin("LDAP_SEARCH_FILTER", app="admin")
sfilter = sfilter % {"user": user}
res = self.conn.search_s(sbase, ldap.SCOPE_SUBTREE, sfilter)
try:
dn = res[0][0]
except IndexError:
return None
return dn
def _crypt_password(self, user, clearpassword):
def _crypt_password(self, clearpassword):
"""Overidding of the crypt_password function (LDAP compliant)
The crypted password in base64 encoded and we prepend the used
algorithm to the returned value. (between {})
:param clearpassword: the clear password
:return: the encrypted password
"""
@@ -106,15 +121,12 @@ class LDAPAuthBackend(object):
def update_user_password(self, user, password, newpassword):
try:
dn = self._find_user_dn(user)
conn = self._get_conn(dn, password)
self.connect_to_server(user, password)
if self.ldap_ad:
newpassword = ('"%s"' % newpassword).encode('utf-16').lstrip('\377\376')
ldif = [(ldap.MOD_REPLACE,
self.pwd_attr,
self._crypt_password(user, newpassword))]
conn.modify_s(dn, ldif)
self.pwd_attr,
self._crypt_password(newpassword))]
self.conn.modify_s(self.user_dn, ldif)
except ldap.LDAPError, e:
raise LDAPException(str(e))
+6
View File
@@ -32,6 +32,12 @@ TwocolsNav.prototype = {
},
display_errors: function(data) {
if (data.errors == undefined) {
if (data.respmsg) {
$("body").notify("error", data.respmsg);
}
return;
}
$.each(data.errors, function(id, value) {
var fullid = "id_" + (data.prefix ? data.prefix + "-" : "") + id;
var $widget = $("#" + fullid);