How to verify that TLS handshaking is completed in Twisted

This is a follow-up to this question: SSL communication failed when no data was sent via Twisted TLSConnection

I installed a simple SSL server that closes the connection as soon as the client connects.

I am testing it with openssl and I got this handshake rejection:

$ openssl s_client -connect localhost:12345 CONNECTED(00000003) 2329:error:140790E5:SSL routines:SSL23_WRITE :ssl handshake failure:s23_lib.c:188: 

The problem is that TLS.Connection.loseConnection does not wait for the completion of the current handshake and simply disconnects the client.

A callback bound to OpenSSL.SSL.Connection.do_handshake would be great ... but unfortunately I don't know if this can be done ... or how to do it.

Any tips on how I can verify what was done using TLS are greatly appreciated. Thank you very much!

Here is the code

 class ApplicationProtocol(Protocol): '''Protocol that closes the connection when connection is made.''' def connectionMade(self): self.transport.loseConnection() # Here is a barebone TLS Server serverFactory = ServerFactory() serverFactory.protocol = ApplicationProtocol server_cert_path = 'server.pem' serverContextFactory = DefaultOpenSSLContextFactory( privateKeyFileName = server_cert_path, certificateFileName = server_cert_path, sslmethod=SSL.SSLv23_METHOD) tlsFactory = TLSMemoryBIOFactory(serverContextFactory, False, serverFactory) reactor.listenTCP(12345, tlsFactory) #reactor.listenSSL(12345, serverFactory, serverContextFactory) 

At the moment, I decide it is really dirty, not 100% valid.

 def tls_lose_connection(self): """ Monkey patching for TLSMemoryBIOProtocol to wait for handshake to end, before closing the connection. Send a TLS close alert and close the underlying connection. """ def close_connection(): self.disconnecting = True if not self._writeBlockedOnRead: self._tlsConnection.shutdown() self._flushSendBIO() self.transport.loseConnection() # If we don't know if the handshake was done, we wait for a bit # and the close the connection. # This is done to avoid closing the connection in the middle of a # handshake. if not self._handshakeDone: reactor.callLater(0.5, close_connection) else: close_connection() TLSMemoryBIOProtocol.loseConnection = tls_lose_connection 
+4
source share
3 answers

The SSL context object can be configured using the "information callback" - Context.set_info_callback. This is a wrapper around SSL_CTX_set_info_callback. A little more convenient (in this case) SSL_set_info_callback for specifying a callback for a single connection, unfortunately, pyOpenSSL was not found.

Among other things, the info callback is called when the handshake ends. With a few acrobatics, you will need to include this notification in the Deferred or some other callback in the protocol.

See the pyOpenSSL documentation set_info_callback and the OpenSSL SSL_CTX_set_info_callback documentation for details.

+4
source

I provide code that implements Jean-Paul's answer.

 class ProxyClientTLSContextFactory(ssl.ClientContextFactory): isClient = 1 def getContext(self): ctx = SSL.Context(SSL.TLSv1_METHOD) logger = logging.GetLogger() def infoCallback(conn, where, ret): # conn is a OpenSSL.SSL.Connection # where is a set of flags telling where in the handshake we are # See http://www.openssl.org/docs/ssl/SSL_CTX_set_info_callback.html logger.debug("infoCallback %s %d %d" % (conn, where, ret)) if where & SSL.SSL_CB_HANDSHAKE_START: logger.debug("Handshake started") if where & SSL.SSL_CB_HANDSHAKE_DONE: logger.debug("Handshake done") ctx.set_info_callback(infoCallback) return ctx 

The problem I encountered inside infoCallback () is that I have no idea how to switch from SSL.Connection back to the associated instance of Twisted Protocol.

What I would like to do is call back my protocol instance after the connection has been completed and the TLS handshake has completed, so I can be sure that I like the certificate verification before continuing.

+5
source

I found the use of loseConnection() unreliable due to a connection problem. This can be called, and the connection is never completely disconnected. So for TLS, I always use abortConnection() . He will ensure that the connection is closed regardless of the state of the handshake.

0
source

Source: https://habr.com/ru/post/1339140/


All Articles