Reputation:
The code I am using:
# Create LDAPObject instance
conn = ldap.initialize(url)
conn.protocol_version=ldap.VERSION3
conn.simple_bind_s(binddn,bindpw)
# This raises:
# ldap.SERVER_DOWN:
{'info': 'error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed', 'desc': "Can't contact LDAP server"}
When I use ldap:// instead of ldaps://, it works correctly.
Can anybody help me figure out why this is?
Thanks. :)
Upvotes: 15
Views: 27705
Reputation: 116
PAY much attention to your protocol and port in your connection string:
Using TLS with python-ldap:
# TLS uses string uri 'ldaP://' (NO 's')
# then the method start_tls_s() will transfer to a secure connection
l = ldap.initialize('ldap://localhost:1390',trace_level=ldapmodule_trace_level,trace_file=ldapmodule_trace_file)
# Set LDAP protocol version used
l.protocol_version=ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTFILE,CACERTFILE)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX,0)
# Now try StartTLS extended operation
l.start_tls_s()
print('***ldap.OPT_X_TLS_VERSION',l.get_option(ldap.OPT_X_TLS_VERSION))
print('***ldap.OPT_X_TLS_CIPHER',l.get_option(ldap.OPT_X_TLS_CIPHER))
# Try an explicit anon bind to provoke failure
l.simple_bind_s('','')
# Close connection
l.unbind_s()
SSL uses 'ldapS://' directly!
And it doesn't use the start_tls_s()
# Create LDAPObject instance
l = ldap.initialize('ldaps://localhost:1391',trace_level=ldapmodule_trace_level,trace_file=ldapmodule_trace_file)
# Set LDAP protocol version used
l.protocol_version=ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTFILE,CACERTFILE)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX,0)
# Try an explicit anon bind to provoke failure
l.simple_bind_s('','')
print('***ldap.OPT_X_TLS_VERSION',l.get_option(ldap.OPT_X_TLS_VERSION))
print('***ldap.OPT_X_TLS_CIPHER',l.get_option(ldap.OPT_X_TLS_CIPHER))
# Close connection
l.unbind_s()
source: original developers github demo initialize.py
Upvotes: 0
Reputation: 108567
I've never used python-ldap over SSL but I believe you have to tell ldap what checks to perform on the server certificate. If this is set to demand (which might be the default), you have to give it valid certs.
See the initialize.py in the Demo directory the source.
Upvotes: 7
Reputation: 274
to ignore certificate errors
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
Upvotes: 13
Reputation: 166871
Try to pass the following environment variable:
LDAPTLS_REQCERT=never
to ignore server certificate which could be expired or invalid.
See:
Upvotes: 2
Reputation: 530
I came here looking for a solution to my problem related to this. This Q&A did not solve my exact problem, but others looking for my exact problem's solution will find the following useful:
For those using SSL/TLS for basic transport encryption and not identity verification (self-signed certificates), you just turn off strict checking of the server certificate:
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW)
This is roughly analogous to setting the OpenLDAP 2.1+ client setting:
tls_checkpeer no
Upvotes: 30