pyopenssl icon indicating copy to clipboard operation
pyopenssl copied to clipboard

Error in do_handshake()

Open LeviPesin opened this issue 5 years ago • 7 comments

Please look into https://github.com/SecureAuthCorp/impacket/issues/866 and https://github.com/SecureAuthCorp/impacket/issues/856. I think that problem is not in impacket, but in pyOpenSSL.

LeviPesin avatar Jun 20 '20 06:06 LeviPesin

For example, if you run following code (require installed impacket) you get [('SSL routines', 'state_machine', 'internal error')]: import impacket.tds from OpenSSL import SSL ms_sql = impacket.tds.MSSQL('10.10.10.27', 1433) ms_sql.connect() ms_sql.preLogin() ctx = SSL.Context(SSL.TLSv1_METHOD) ctx.set_cipher_list('RC4, AES256') (you get warning here) tls = SSL.Connection(ctx, None) tls.set_connect_state() tls.do_handshake() (here you get error)

LeviPesin avatar Jun 20 '20 10:06 LeviPesin

Actually, it is not working even without impacket and without warning :-) For example, this code does not work: from OpenSSL import SSL ctx = SSL.Context(SSL.TLSv1_METHOD) ctx.set_cipher_list('RC4, AES256'.encode()) tls = SSL.Connection(ctx, None) tls.set_connect_state() tls.do_handshake()

LeviPesin avatar Jun 27 '20 19:06 LeviPesin

I can hit a similar issue with this:

import socket
import OpenSSL
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(100)
ctx = OpenSSL.SSL.Context( OpenSSL.SSL.TLSv1_2_METHOD)

def print_chain(context, hostname, port):
    print('Connecting to {0}'.format(hostname))
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock = OpenSSL.SSL.Connection(context=context, socket=sock)
    sock.settimeout(5)
    sock.connect((hostname, port))
    sock.setblocking(1)
    sock.do_handshake()
    for cert in sock.get_peer_cert_chain():
        print('   s:{0}'.format(cert.get_subject()))
        print('   i:{0}'.format(cert.get_issuer()))
    sock.shutdown()
    sock.close()

Servers that are checking ServerName error while servers that don't work fine. For example, things that use Go's autocert will fail with the above script. (thanks to @jrick for tracking that bit down!)

qbit avatar Jul 24 '20 16:07 qbit

I have confirmed this happens on:

OS Library
OpenBSD-current LibreSSL 3.2.1
macOS 11.0 Big Sur LibreSSL 2.8.3
NixOS 20.3.2625 OpenSSL 1.1.1g 21 Apr 2020

qbit avatar Jul 24 '20 22:07 qbit

In my example issue happens on last Ubuntu, OpenSSL 1.1.1g 21 Apr 2020, and Python 3.8 (on Python 3.7 there is no issue).

LeviPesin avatar Jul 27 '20 07:07 LeviPesin

Turns out my issue looked very much like this one, and my test script was not quite exercising the full issue.

Currently on LibreSSL (on OpenBSD-current as of 2020-07-01ish) TLS 1.3 does not support the info callback. This caused the same result as seen in the script I posted earlier. In the example script if one sets sock.set_tlsext_host_name(hostname.encode()) it will work as expected.

I was mistaken in my assumption that sock.set_tlsext_host_name(hostname.encode()) should happen by default.

qbit avatar Jul 27 '20 14:07 qbit

I'm sorry we've been slow to triage this. Can someone please provide a complete and self-contained example for reproducing this?

alex avatar Nov 27 '20 15:11 alex