Search code examples
pythonflaskldappython-ldap

Python ldap function behaves differently when called in flask


So I'm trying get auto-complete to work with python-ldap and flask. Here's a test script ldapA.py:

import ldap

#first you must open a connection to the server

def query():
    try:
        l = ldap.open("server.net")


        ## searching doesn't require a bind in LDAP V3.  If you're using LDAP v2, set the next line appropriately
        ## and do a bind as shown in the above example.
        # you can also set this to ldap.VERSION2 if you're using a v2 directory
        # you should  set the next option to ldap.VERSION2 if you're using a v2 directory
        l.protocol_version = ldap.VERSION3
        l.set_option(ldap.OPT_REFERRALS, 0)
        username="CN=user user,OU=bbbgbg,OU=bdbfd,DC=dsffd,DC=net"
        passw="adsada"

        l.simple_bind_s(username,passw)
    except ldap.LDAPError, e:
        print e
        # handle error however you like


    ## The next lines will also need to be changed to support your search requirements and directory
    baseDN = "ou=xds, ou=sd, dc=sd, dc=net"
    searchScope = ldap.SCOPE_SUBTREE
    ## retrieve all attributes - again adjust to your needs - see documentation for more options
    retrieveAttributes = ['name'] 
    searchFilter = "name=*jace*"

    try:
        ldap_result_id = l.search(baseDN, searchScope, searchFilter, retrieveAttributes)
        result_set = []
        while 1:
            result_type, result_data = l.result(ldap_result_id, 0)
            if (result_data == []):
                break
            else:
                ## here you don't have to append to a list
                ## you could do whatever you want with the individual entry
                ## The appending to list is just for illustration. 
                if result_type == ldap.RES_SEARCH_ENTRY:
                    result_set.append(result_data)
                res = result_set[0]
                res1 = res[0]
                res2 = res1[1]
                res3 = res2["name"]
        print res3[0]
    except ldap.LDAPError, e:
        print e


query()

It works as intended when I run it. It gives me my name from the AD.

Now when I call it from flask like this:

from flask import render_template
from app import app
from flask import request
from ldapA import query
@app.route('/')
@app.route('/index')
def index():
  return render_template("index.html")

@app.route('/autocomplete', methods=['GET'])
def autocomplete():
    return query()

I get:

  127.0.0.1 - - [19/Jul/2017 14:08:58] "GET /autocomplete HTTP/1.1" 500 -
    Traceback (most recent call last):
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1997, in __call__
        return self.wsgi_app(environ, start_response)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app
        response = self.handle_exception(e)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception
        reraise(exc_type, exc_value, tb)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
        response = self.full_dispatch_request()
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
        reraise(exc_type, exc_value, tb)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
        rv = self.dispatch_request()
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
        return self.view_functions[rule.endpoint](**req.view_args)
      File "/home/jgar/receptionsignin/app/views.py", line 13, in autocomplete
        return query()
      File "/home/jgar/receptionsignin/ldapA.py", line 36, in query
        result_type, result_data = l.result(ldap_result_id, 0)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/ldap/ldapobject.py", line 703, in result
        resp_type, resp_data, resp_msgid = self.result2(msgid,all,timeout)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/ldap/ldapobject.py", line 707, in result2
        resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all,timeout)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/ldap/ldapobject.py", line 714, in result3
        resp_ctrl_classes=resp_ctrl_classes
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/ldap/ldapobject.py", line 734, in result4
        resp_data = self._bytesify_results(resp_data, with_ctrls=add_ctrls)
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/ldap/ldapobject.py", line 266, in _bytesify_results
        for (dn, fields) in results
      File "/home/jgar/receptionsignin/flask/lib/python2.7/site-packages/ldap/ldapobject.py", line 219, in _maybe_rebytesify_text
        assert isinstance(value, text_type), "Should return text, got bytes instead (%r)" % (value,)
    AssertionError: Should return text, got bytes instead ('CN=sdsddsc,OU=sds,OU=sds,DC=sdds,DC=net')

I know that this line causes the trouble:

ldap_result_id = l.search(baseDN, searchScope, searchFilter, retrieveAttributes)

But I'm stumped as to why it happens when called in flask and not when run with python ldapA.py. It seems to be the ldap lib internal error, but why does it only happen in flask and how could I fix it? Thanks guys!


Solution

  • Turns out it was a unicode problem, for anyone having the same error: Go to ldpaobject.py(whererver you have python-ldap installed) Change

    if PY2:
      text_type = unicode
    else:
      text_type = str
    

    to just

    text_type = str
    

    python-ldap should now work in flask