Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect with Python IMAP4_SSL and self-signed server SSL cert?

I'm using python3 and imaplib to connect to an Exchange server. The Exchange server uses a self-signed certificate created for the hostname 'my.server.fqdn'. After a recent OS upgrade on my workstation (Ubuntu 14.04) my python script no longer works.

The basic snippet of code I'm using is here:

#!/usr/bin/python3

import imaplib
import socket
import ssl
import getpass

passwd = getpass.getpass()
mail =  imaplib.IMAP4_SSL('my.server.fqdn', 1143)  
mail.login('mike', passwd)
mail.list()
mail.select("INBOX")

The code worked fine prior to the upgrade. Now this code produces this error:

Traceback (most recent call last):
  File "./example.py", line 9, in <module>
    mail =  imaplib.IMAP4_SSL('my.server.fqdn', 1143)  
  File "/usr/lib/python3.4/imaplib.py", line 1222, in __init__
    IMAP4.__init__(self, host, port)
  File "/usr/lib/python3.4/imaplib.py", line 181, in __init__
    self.open(host, port)
  File "/usr/lib/python3.4/imaplib.py", line 1236, in open
    IMAP4.open(self, host, port)
  File "/usr/lib/python3.4/imaplib.py", line 257, in open
    self.sock = self._create_socket()
  File "/usr/lib/python3.4/imaplib.py", line 1228, in _create_socket
    server_hostname=server_hostname)
  File "/usr/lib/python3.4/ssl.py", line 364, in wrap_socket
    _context=self)
  File "/usr/lib/python3.4/ssl.py", line 578, in __init__
    self.do_handshake()
  File "/usr/lib/python3.4/ssl.py", line 805, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: TLSV1_ALERT_INTERNAL_ERROR] tlsv1 alert internal error (_ssl.c:598)

It's not apparent to me if python is having a problem with the self-signed certificate, SSL version, or if there is something new with python 3 which doesn't work with my old code.

I do have a PEM file from the Exchange server which allows me to connect to the server using curl. Authentication fails, however the checks curl does during the SSL handshake seem to work OK. I do have to supply curl the --sslv3 option along with a path to the PEM file for that to work. If that's what I need to do with python to get this working again, how do I go about supplying python with the same information?

curl session is here:

$ curl -vvv --sslv3 https://my.server.fqdn:1143 --cacert ~/my_server_fqdn.pem 
    * Rebuilt URL to: https://my.server.fqdn:1143/
    * Hostname was NOT found in DNS cache
    *   Trying 10.10.10.10...
    * Connected to my.server.fqdn (10.10.10.10) port 1143 (#0)
    * successfully set certificate verify locations:
    *   CAfile: /home/username/my_server_fqdn.pem
      CApath: /etc/ssl/certs
    * SSLv3, TLS handshake, Client hello (1):
    * SSLv3, TLS handshake, Server hello (2):
    * SSLv3, TLS handshake, CERT (11):
    * SSLv3, TLS handshake, Server key exchange (12):
    * SSLv3, TLS handshake, Server finished (14):
    * SSLv3, TLS handshake, Client key exchange (16):
    * SSLv3, TLS change cipher, Client hello (1):
    * SSLv3, TLS handshake, Finished (20):
    * SSLv3, TLS change cipher, Client hello (1):
    * SSLv3, TLS handshake, Finished (20):
    * SSL connection using ECDHE-RSA-AES256-SHA
    * Server certificate:
    *        subject: O=fqdn; O=SERVER; OU=M; CN=my.server.fqdn
    *        start date: 2013-07-29 20:59:04 GMT
    *        expire date: 2023-07-27 20:59:04 GMT
    *        common name: my.server.fqdn (matched)
    *        issuer: O=fqdn; O=SERVER; OU=M; CN=my.server.fqdn
    *        SSL certificate verify ok.
    > GET / HTTP/1.1
    > User-Agent: curl/7.35.0
    > Host: my.server.fqdn:1143
    > Accept: */*
    > 
    * OK [CAPABILITY IMAP4REV1 AUTH=LOGIN MOVE] IMAP4rev1 server ready
    GET BAD command authentication required
    User-Agent: BAD command authentication required
    Host: BAD command authentication required
    Accept: BAD command authentication required
    * SSLv3, TLS alert, Client hello (1):
    * Connection #0 to host my.server.fqdn left intact
like image 327
Koko Avatar asked Aug 14 '14 21:08

Koko


1 Answers

Apparently this problem is due to one or more versions of TLS protocol being disabled in the openssl package on Ubuntu 12.04 and 14.04. I ended up using an ssl context in python3 and forcing SSL version 3 for the connection. This appears to work now. Really hope this helps anyone struggling with the same problem.

#!/usr/bin/python3

import imaplib
import socket
import ssl
import getpass

ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)  
passwd = getpass.getpass()
mail =  imaplib.IMAP4_SSL('my.server.fqdn', 1143, ssl_context=ctx)
mail.login('mike', passwd)
mail.select('INBOX', 1)
typ, uids = mail.uid("SEARCH", None, "ALL")

uids = uids[0].split()
for u in uids:
   print ("found uid " , u)

mail.close()
mail.logout()
del mail
like image 143
Koko Avatar answered Oct 23 '22 23:10

Koko