ldap3 operation: SEARCH seems to fail (search_filter syntax vs RFC4515)

kfkhalili picture kfkhalili · Sep 21, 2015 · Viewed 8.7k times · Source

Edit: tl;dr - The search_filter argument used in SEARCH might be non conforming with RFC4515.

I've got a Django server running version 1.8.4 on Ubuntu 14.04. I'm using Python 3.4 and for that I'm trying to configure LDAP authentication using ldap3.

This is part of an upgrade to the versions named above from 1.6.2, 12.04, and 2.7.3, respectively. Everything was working correctly, so I assume that the problem is on my end and not with the authentication server.

The way this works is I've got a file called authenticate_user.py which receives the username and password passed through an HTML form as shown below.

def authenticateStudent(request):
    username = request.POST.get('username','')
    logger.info("User " + username + " has logged in.")
    password = request.POST.get('password','')
    x = Auth(username, password)
    retVal = x.AuthenticatePy()
    logger.info('retVale is '+str(retVal)) #this returns False
    #more code and more logging

The method instantiates an object from the Auth class (shown below), stores the username and password within, and then calls the AuthenticatePy() method in that class.

import logging
import sys
import os.path,subprocess
import ldap3 as ldap
from ldap3 import Connection, Server, SIMPLE, SYNC, SUBTREE, ALL


logger = logging.getLogger('Submission')

class Auth():

    studentName = ""
    studentEmail = ""
    studentMatrik = ""

    def __init__(self, username, password):
        self.username = username
        self.password = password

    def AuthenticatePy(self):
        user_dn = "cn="+self.username+",ou=users,ou=data,ou=prod,ou=authserver,dc=domain,dc=tld"
        base_dn = "dc=domain,dc=tld"
        server = Server("authserver.domain.tld", port=636, use_ssl=True)

        filter = "uid="+self.username #might be incorrect
        try:
            #if authentication successful, get the full user data
            connect = Connection(server, user=user_dn, password=self.password)
            connect.bind()
            logger.info('Connection Bind Complete!') #the last logged message from this method
            result = connect.search(search_base=base_dn, search_filter=filter, search_scope=SUBTREE)
            logger.info('SEARCHING COMPLETE') #does not appear in the log
            # return all user data results
            connect.unbind()
            uname = result[0][1]['cn'][0]
            studentName = result[0][1]['fullName'][0]
            studentEmail = result[0][1]['imHauptEMail'][0]
            studentMatrik = result[0][1]['imMatrikelNr'][0]
            logger.info('studentName is '+str(studentName))
            if uname == self.username :
                return studentName + '$' + studentEmail + '$' + studentMatrik
            else:
                return False
        except ldap.LDAPExceptionError:
            connect.unbind()
            return False

The last log message I'm seeing is 'Connection Bind Complete!' and I'm not really sure what's breaking. Any idea what I'm doing wrong?

Edit: I've been troubleshooting this for a while and I'm beginning to think that the problem could be in the search_filter argument I'm passing the search function. The ldap3 documentation on the SEARCH operation states that the filter string should be RFC4515 compliant, and I'm not sure I'm providing that.

Answer

cannatag picture cannatag · Sep 21, 2015

I'm the author of ldap3. The ldap filter must be included in parenthesis. Please try adding leading and traling parenthesis to the filter:

filter = "(uid="+self.username + ")"

Bye, Giovanni