[Twisted-Python] Determine TLS version from within request handler ? (twisted web)

Rob Meijer rmeijer at xs4all.nl
Mon Nov 11 01:45:05 MST 2013


On Wed, November 6, 2013 15:38, exarkun at twistedmatrix.com wrote:
> On 11:43 am, rmeijer at xs4all.nl wrote:
>>I'm using twisted web for an https connection. At first I start with
>>creating and configuring a ssl.DefaultOpenSSLContextFactory derived
>>class
>>that disables SSLv2 and SSLv3. So (basically we're left with TLS1.0 and
>>up) and forces the use of a single strong (non RC4 but BEAST
>>vulnerable)
>>cipher.
>>
>>Than I have a http.HTTPFactory derived class with a 'buildProtocol'that
>>return a http.HTTPChannel derived object, that in turn returns a
>>http.Request derived object.
>>
>>Than reactor.listenSSL is invoked with both the SSL factory and the
>>HTTP
>>factory. Now my problem. I don't really understand how these two are
>>connected once the request handler gets invoked.
>>
>>What I would like to do is that I would want to allow TLS1.0 users to
>>use
>>the server, but only after explicitly agreeing that they understand the
>>risks involved with using an old BEAST vulnerable browser.
>>
>>Is there any way to retrieve info on what TLS version has been
>>negotiated
>>from within the HTTP request handler? I've been walking the 'self'
>>object
>>a bit, and self.transport.getHandle() seems to have some tls stuff like
>>'get_cipher_list' and 'get_peer_certificate', but the simple TLS
>>version
>>number does not seem to be available.
>
> The object you get back from `self.transport.getHandle()` happens to be
> an object from pyOpenSSL - an instance of OpenSSL.SSL.Connection.  While
> reading the following, though, bear in mind that `getHandle` doesn't
> make much of a promise about what it will return.  Other transports may
> return something else and future versions of Twisted may change the
> result as well.
>
> The API that OpenSSL appears to offer for determining what protocol
> version is in use appears to be SSL_get_version().  This returns a
> string like "SSLv2" or "TLSv1" (the documentation doesn't say anything
> about TLSv1.1 or TLSv1.2 but *presumably* if you have a version of
> OpenSSL that implements either of these protocols and one of them is
> negotiated on a connection then SSL_get_version() will identify them in
> its result).
>
> pyOpenSSL, however, does not expose this method.  So in order to get the
> information you need you may need to contribute a binding for this
> method to pyOpenSSL.
>
> Jean-Paul

Hi Jean-Paul,

Tnx very much for your answer. I've now ended up with what I think is a
bit of a hack. I've consulted the wikipedia page on TLS :

http://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers

and added some code that checks the browser version as reported un the
user-agent header against the minimum version of major browsers that
report to have TLS1.1 support both implemented and enabled by default.
I'm not fully satisfied with this one, but unfortunately it seems to be
the only viable option for my current project :-(


Tnx,

Rob




More information about the Twisted-Python mailing list