[python3-ldap] Trouble with STARTTLS
python3ldap
python3ldap at gmail.com
Tue Apr 29 22:24:32 CEST 2014
Hi Mark, thanks for your great job in debugging this issue. I refactored
the start_tls code in version 0.9.1 and must have messed up the code base.
There should be no redundant checking for site names and name checking
cannot obviuosly performed before handshake. I will fix this bug as soon as
I can.
In the meanwhile I apologize for wasting your time while trying to
understand what was wrong.
Bye,
gc
Il martedì 29 aprile 2014, Mark E. Haase <mehaase at gmail.com> ha scritto:
> Thanks for the reply, gc. I tried with Python 3 with different but still
> unsuccessful results:
>
> Here is one machine I tried on:
>
> $ python3 --version
> Python 3.2.3
> $ python3 test.py
> Traceback (most recent call last):
> File "test.py", line 15, in <module>
> ldap_handle.start_tls()
> File "/usr/local/lib/python3.2/dist-packages/ldap3/core/connection.py",
> line 535, in start_tls
> if self.server.tls.start_tls(self):
> File "/usr/local/lib/python3.2/dist-packages/ldap3/core/tls.py", line
> 118, in start_tls
> return self._start_tls(connection)
> File "/usr/local/lib/python3.2/dist-packages/ldap3/core/tls.py", line
> 121, in _start_tls
> connection.socket = self.wrap_socket(connection, False)
> File "/usr/local/lib/python3.2/dist-packages/ldap3/core/tls.py", line
> 91, in wrap_socket
> check_hostname(wrapped_socket, connection.server.host,
> self.valid_names)
> File "/usr/local/lib/python3.2/dist-packages/ldap3/core/tls.py", line
> 203, in check_hostname
> ssl.match_hostname(server_certificate, host_name) # raise
> CertificateError if certificate doesn't match server name
> File "/usr/lib/python3.2/ssl.py", line 141, in match_hostname
> raise ValueError("empty or no certificate")
> ValueError: empty or no certificate
>
> Here's another:
>
> $ python3 --version
> Python 3.4.0
> $ python3 test.py
> Traceback (most recent call last):
> File "test.py", line 15, in <module>
> ldap_handle.start_tls()
> File "/usr/local/lib/python3.4/dist-packages/ldap3/core/connection.py",
> line 535, in start_tls
> if self.server.tls.start_tls(self):
> File "/usr/local/lib/python3.4/dist-packages/ldap3/core/tls.py", line
> 118, in start_tls
> return self._start_tls(connection)
> File "/usr/local/lib/python3.4/dist-packages/ldap3/core/tls.py", line
> 121, in _start_tls
> connection.socket = self.wrap_socket(connection, False)
> File "/usr/local/lib/python3.4/dist-packages/ldap3/core/tls.py", line
> 91, in wrap_socket
> check_hostname(wrapped_socket, connection.server.host,
> self.valid_names)
> File "/usr/local/lib/python3.4/dist-packages/ldap3/core/tls.py", line
> 196, in check_hostname
> server_certificate = sock.getpeercert()
> File "/usr/lib/python3.4/ssl.py", line 648, in getpeercert
> return self._sslobj.peer_certificate(binary_form)
> ValueError: handshake not done yet
>
> This is apparently a new error in Python 3.4, according to the python docs.
>
> I took a closer look at core/tls.py, and I see in wrap_socket(), lines
> 90-91 perform a hostname check, but these lines are redundant with lines
> 128-129 in _start_tls(). Furthermore, these lines execute *before* the
> handshake at line 123. I tried making the following change and my test
> script doesn't throw any exceptions. I haven't tested it any deeper yet
> because I wanted to get your feedback.
>
> core/tls.py:
> 84 def wrap_socket(self, connection, do_handshake=False):
> 85 """
> 86 Adds TLS to a plain socket and returns the SSL socket
> 87 """
> 88 wrapped_socket = ssl.wrap_socket(connection.socket,
> keyfile=self.private_key_file, certfile=self.certificate_file, server
> _side=False, cert_reqs=self.validate, ssl_version=self.version,
> ca_certs=self.ca_certs_file, do_handshake_on_connect=do_handshake )
> 89
> 90 if do_handshake and self.validate == ssl.CERT_REQUIRED or
> self.validate == ssl.CERT_OPTIONAL:
> 91 check_hostname(wrapped_socket, connection.server.host,
> self.valid_names)
> 92
> 93 return wrapped_socket
>
> At line 90 I added the "do_handshake and" condition. I believe this would
> fix the starttls operation without breaking any existing callers to
> wrap_socket.
>
> What do you think?
>
>
>
> On Tue, Apr 29, 2014 at 2:23 AM, python3ldap <python3ldap at gmail.com<javascript:_e(%7B%7D,'cvml','python3ldap at gmail.com');>
> > wrote:
>
>>
>> Hello Mark, could you try the same operation with python 3? Python 2 is
>> (with no apparent reason) missing a fundamental check in ssl handshake
>> (match hostname in certificate with a valid list of names), so I backported
>> it from 3 to 2 (the match_hostname_backport function). If your code works
>> with python 3 maybe there is a problem in the backport function. Or you can
>> try to disable the whole match_hostname passing a valid_names='*' parameter
>> in the Tls() creation.
>>
>> Bye,
>> gc
>>
>>
>> Il martedì 29 aprile 2014, Mark E. Haase <mehaase at gmail.com<javascript:_e(%7B%7D,'cvml','mehaase at gmail.com');>>
>> ha scritto:
>>
>> I really like python3-ldap. Much cleaner than building on top of OpenLDAP
>>> :)
>>>
>>> I can get TLS working on port 636, but I can't figure out how to get
>>> Start TLS on port 389. Here's what I have so far (Python 2.7):
>>>
>>> 01 import ldap3
>>> 02 import os
>>> 03 import ssl
>>> 04
>>> 05 host = "ldap.*************.net"
>>> 06 port = 389
>>> 07 username = "cn=admin,dc=*************,dc=net"
>>> 08 password = "*************"
>>> 09 base_path = os.path.dirname(os.path.realpath(__file__))
>>> 10
>>> 11 tls = ldap3.Tls(validate=ssl.CERT_REQUIRED,
>>> ca_certs_file=os.path.join(base_path, "goodca"))
>>> 12 ldap_server = ldap3.Server(host, port=port, use_ssl=False, tls=tls)
>>> 13 ldap_handle = ldap3.Connection(ldap_server, user=username,
>>> password=password)
>>> 14 ldap_handle.open()
>>> 15 ldap_handle.start_tls()
>>> 16 ldap_handle.bind()
>>>
>>> I'm ~100% sure that "goodca" is not the problem, because I've validated
>>> it with openssl s_client, gnutls-cli, ldapsearch, and python-ldap. It's PEM
>>> encoded. When I run this example, I get this exception:
>>>
>>> mhaase at luci:~/luci/bin$ python test.py
>>> Traceback (most recent call last):
>>> File "test.py", line 15, in <module>
>>> ldap_handle.start_tls()
>>> File
>>> "/usr/local/lib/python2.7/dist-packages/ldap3/core/connection.py", line
>>> 535, in start_tls
>>> if self.server.tls.start_tls(self):
>>> File "/usr/local/lib/python2.7/dist-packages/ldap3/core/tls.py", line
>>> 118, in start_tls
>>> return self._start_tls(connection)
>>> File "/usr/local/lib/python2.7/dist-packages/ldap3/core/tls.py", line
>>> 121, in _start_tls
>>> connection.socket = self.wrap_socket(connection, False)
>>> File "/usr/local/lib/python2.7/dist-packages/ldap3/core/tls.py", line
>>> 91, in wrap_socket
>>> check_hostname(wrapped_socket, connection.server.host,
>>> self.valid_names)
>>> File "/usr/local/lib/python2.7/dist-packages/ldap3/core/tls.py", line
>>> 206, in check_hostname
>>> match_hostname_backport(server_certificate, host_name)
>>> File "/usr/local/lib/python2.7/dist-packages/ldap3/core/tls.py", line
>>> 168, in match_hostname_backport
>>> raise ValueError("empty or no certificate")
>>> ValueError: empty or no certificate
>>>
>>> Any ideas what I'm doing wrong? Any help would be greatly appreciated...
>>> I've been struggling with openldap/python-ldap/python3-for 12 hours today!!
>>>
>>
>>
>> --
>> Have fun,
>> gc
>>
>>
>
--
Have fun,
gc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python3-ldap/attachments/20140429/2878f42f/attachment-0001.html>
More information about the python3-ldap
mailing list