Re: TLS 1.3 and SNI; test script included
Charles Cazabon <[email protected]>
| Newsgroups | gmane.mail.getmail.user |
|---|---|
| Message-ID | <[email protected]> |
[email protected] <[email protected]> wrote: > > Wodan> ./test-imap.py imap.gmail.com <http://imap.gmail.com/> > Traceback (most recent call last): > File "./test-imap.py", line 11, in <module> > ssl_version=ssl.PROTOCOL_TLS, ca_certs=None, > AttributeError: 'module' object has no attribute 'PROTOCOL_TLS' Indeed, that value isn't present before 2.7.13. If you care to try, here's an updated version that may fail for different reasons ;) Charles -- ----------------------------------------------------------------------- Charles Cazabon GPL'ed software available at: http://pyropus.ca/software/ ----------------------------------------------------------------------- --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
test-imap.py
(text/x-python, 3.4 KB)
#!/usr/bin/env python2.7
import sys
import imaplib
import socket
import ssl
import hashlib
def wrap_socket(sock, keyfile=None, certfile=None,
server_side=False, cert_reqs=ssl.CERT_NONE,
ssl_version=ssl.PROTOCOL_TLS, ca_certs=None,
do_handshake_on_connect=True,
suppress_ragged_eofs=True,
ciphers=None, server_hostname=None):
return ssl.SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
server_side=server_side, cert_reqs=cert_reqs,
ssl_version=ssl_version, ca_certs=ca_certs,
do_handshake_on_connect=do_handshake_on_connect,
suppress_ragged_eofs=suppress_ragged_eofs,
ciphers=ciphers, server_hostname=server_hostname)
ssl.wrap_socket = wrap_socket
PROTO_BEST = getattr(ssl, 'PROTOCOL_TLS', None)
#######################################
class IMAP4_SSL_EXTENDED(imaplib.IMAP4_SSL):
# Similar to above, but with extended support for SSL certificate checking,
# fingerprints, etc.
def __init__(self, host, port=imaplib.IMAP4_SSL_PORT,
ssl_version=None, use_sni=False):
self.ssl_version = ssl_version
self.use_sni = use_sni
imaplib.IMAP4_SSL.__init__(self, host, port, keyfile=None, certfile=None)
def open(self, host='', port=imaplib.IMAP4_SSL_PORT):
self.host = host
self.port = port
self.sock = socket.create_connection((host, port))
extra_args = {}
if self.ssl_version:
extra_args['ssl_version'] = self.ssl_version
if self.use_sni:
extra_args['server_hostname'] = self.host
self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,
**extra_args)
self.file = self.sslobj.makefile('rb')
has_sni = getattr(ssl, 'HAS_SNI', None)
if has_sni is None:
raise SystemExit('no SNI support')
if not has_sni:
raise SystemExit('OpenSSL - no SNI support')
has_tls13 = getattr(ssl, 'HAS_TLSv1_3', None)
if has_tls13 is None:
raise SystemExit('no TLS1.3 support')
if not has_tls13:
raise SystemExit('OpenSSL - no TLS1.3 support')
server = sys.argv[1]
port = imaplib.IMAP4_SSL_PORT
if len(sys.argv) == 3:
port = int(sys.argv[2])
print 'Connecting to %s:%d' % (server, port)
certhash_nosni = None
certhash_sni = None
try:
conn = IMAP4_SSL_EXTENDED(
server, port, ssl_version=PROTO_BEST, use_sni=False
)
sslobj = conn.ssl()
peercert = sslobj.getpeercert(True)
certhash_nosni = hashlib.sha256(peercert).hexdigest()
ssl_cipher = sslobj.cipher()
print 'No SNI - got cipher %s' % str(ssl_cipher)
except Exception as o:
sys.stderr.write('TLS 1.3, no SNI - connection failed (%s)\n' % o)
else:
conn.logout()
try:
conn = IMAP4_SSL_EXTENDED(
server, port, ssl_version=PROTO_BEST, use_sni=True
)
sslobj = conn.ssl()
peercert = sslobj.getpeercert(True)
certhash_sni = hashlib.sha256(peercert).hexdigest()
ssl_cipher = sslobj.cipher()
print 'SNI - got cipher %s' % str(ssl_cipher)
except Exception as o:
sys.stderr.write('TLS 1.3, with SNI - connection failed (%s)\n' % o)
else:
conn.logout()
if certhash_nosni and certhash_sni and certhash_nosni != certhash_sni:
sys.stderr.write('Different certs for no-SNI and SNI: %s vs %s\n'
% (certhash_nosni, certhash_sni))