0

I'm trying to connect to an imap mail server using only TLSv1 in Python 3.4.

After much troubleshooting (most of which determined that the mail server only supports TLSv1), I've found that I can connect to the server using openssl:

openssl s_client -connect mail.calpoly.edu:993 -tls1

as well as with the sockets package in Python 2.7:

Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> import socket
>>>
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> ssl_sock = ssl.wrap_socket(sock=sock, ssl_version=ssl.PROTOCOL_TLSv1)
>>> ssl_sock.connect(('mail.calpoly.edu', 993))
>>> ssl_sock
<ssl.SSLSocket object at 0x7fbab6e7aed8>

When I try to connect in Python 3.4, however, I get a Handshake error:

Python 3.4.0 (default, Apr 11 2014, 13:05:11) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> import socket
>>> 
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> ssl_sock = ssl.wrap_socket(sock=sock, ssl_version=ssl.PROTOCOL_TLSv1)
>>> ssl_sock.connect(('mail.calpoly.edu', 993))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/ssl.py", line 841, in connect
    self._real_connect(addr, False)
  File "/usr/lib/python3.4/ssl.py", line 832, in _real_connect
    self.do_handshake()
  File "/usr/lib/python3.4/ssl.py", line 805, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:598)

It seems like Python 3.4 tries to use sslv3 even though I tell it not to.

Does anyone know why this is happening and how I can work around it?

P.S. - I'll be using imaplib in the code that will interface with the server. I used sockets in this example to highlight that this doesn't seem to be just an issue with the imaplib package.

kavdev
  • 480
  • 4
  • 14
  • How did you install (and build, if relevant) your Python 2.7 and 3.4? Is it possible that one was built with older SSL libraries? – abarnert Dec 06 '14 at 02:42
  • Both were installed via apt-get on Ubuntu 14.04 LTS with OpenSSL version 1.0.1f. – kavdev Dec 06 '14 at 03:59

1 Answers1

3

...most of which determined that the mail server only supports TLSv1

Does this mean that the server will croak on any other handshake? Typically a client will start with the best protocol it can (like TLSv12) and if the server does not support it, then it will just reply with a lower protocol (like TLSv1 in this case). But, some servers are just broken or there is a broken middlebox in between.

[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure
....
It seems like Python 3.4 tries to use sslv3 even though I tell it not to.

Not necessarily. TLS1.0 is just SSL3.1 and lots of TLS handling is actually done with SSLv3 functions. So this error message might be confusing.

When checking the server out with some tool it looks like, that it

  • will return "unsupported protocol" with SSL3.0, which is fine.
  • will croak with with TLS1.1 instead of just returning with TLS1.0. This means that the server or some middlebox in between is seriously broken.
  • will only accept RC4-MD5 as a cipher and croak on any other ciphers. This also makes it broken because it should return "no shared ciphers" on unsupported ciphers instead.

RC4-MD5 also is the reason for not working with python 3.4. Contrary to python 2.7 there is a more secure default cipher set in python 3.4 which includes "..:!MD5". This means the python 3.4 client will not offer RC4-MD5 as cipher and thus the handshake will fail because of no shared ciphers.

Fix would be to fix the broken server. Workaround might be to explicitly set the cipher for your connecion, i.e. wrap_socket( ... , ciphers="RC4-MD5") or similar

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Thank you so much - explicitly stating ciphers worked! I didn't even think to check the server's cipher suite. – kavdev Dec 06 '14 at 06:20