Python 3.4 - Connect to imap server using only TLSv1
Question: 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.


Answer: > ...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](https://github.com/noxxi/p5-io-
socket-ssl/blob/master/util/analyze-ssl.pl) 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

