cannatag / ldap3

a strictly RFC 4510 conforming LDAP V3 pure Python client. The same codebase works with Python 2. Python 3, PyPy and PyPy3
Other
873 stars 269 forks source link

Undocumented workaround for binding to GLAuth server #920

Open scossu opened 3 years ago

scossu commented 3 years ago

I am setting up a GLAuth LDAP server to test an application in a self-contained CI environment.

I set up some mock users and a default search base, and if I test the environment with ldapsearch, I can get an admin user to list all other users:

ldapsearch -LLL -H ldap://localhost:3893 -D 'uid=test_admin,ou=admins,dc=glauth,dc=com' -w test -x -b 'dc=glauth,dc=com'

However, a similar request with ldap3 results in a failure reporting that the searchDN is empty:

        conn = Connection(
            server="ldap://localhost:3893", "user=uid=test_admin,ou=admins,dc=glauth,dc=com",
          password="test", auto_bind=False, raise_exceptions=True
        )
        conn.bind()

The bind() command fails with the exception ldap3.core.exceptions.LDAPInsufficientAccessRightsResult: LDAPInsufficientAccessRightsResult - 50 - insufficientAccessRights - None - None - searchResDone - None

GLAuth logs:

ldap_1         | 19:00:57.432781 Bind ▶ DEBU 05b Bind request: bindDN: uid=test_admin,ou=admins,dc=glauth,dc=com, BaseDN: dc=glauth,dc=com, source: 172.18.0.1:39616
ldap_1         | 19:00:57.432962 Bind ▶ DEBU 05c Bind success as uid=test_admin,ou=admins,dc=glauth,dc=com from 172.18.0.1:39616
ldap_1         | 19:00:57.435265 Search ▶ DEBU 05d Search request as uid=test_admin,ou=admins,dc=glauth,dc=com from 172.18.0.1:39616 for (objectClass=*)
ldap_1         | 2021/02/17 19:00:57 handleSearchRequest error LDAP Result Code 50 "Insufficient Access Rights": Search Error: search BaseDN  is not in our BaseDN dc=glauth,dc=com

It seems like GLAuth is performing a search for the user after binding, and it's failing because I did not specify a search base. I did not see any parameter in the Connection() constructor nor in the bind() method.

However, I found an undocumented read_server_info parameter for bind() which, if set to False, seems to prevent the extra search step and results in a successful operation.

This problem does not occur with my LDAP production server (I believe OpenLDAP) where I am able to use the auto_bind option.

Can this special case and the read_server_info option be documented (if that is indeed the best way to solve this)? Thanks.

zorn96 commented 3 years ago

hi @scossu ! so it's not searching for the user, it's searching the root DSE as the user. this is actually in accordance with RFCs 4511 and 4512 - the root DSE contains information such as support LDAP versions, supported SASL mechanisms for authentication, etc. which can be important to read before authenticating. it also includes things such as supported controls, and schema information

the library does read this info by default, so it can provide better validation for client actions

it seems like your test environment is restricting reads to the root DSE. this is fine, and can be worked around as you described. we can definitely try to update the docs to explain the root DSE a bit better, when it's read, what it impacts, etc. - I just wanted to explain why it's working for one and not the other. it's relatively standard to allow unauthenticated searches of the root DSE, and many clients (not just ldap3) will try to read it to determine supported auth mechanisms before authenticating. so if you're going to use other clients too, it's something to be aware of