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

Werner Thie werner at thieprojects.ch
Mon Nov 11 09:49:50 MST 2013


On 11/10/13 10:45 PM, Rob Meijer wrote:
> 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 :-(
>

Hi Rob

Seeing that you are checking the UA header, I have a bit of information 
concerning UA detection code, which lead to me filing a bug report for 
nevow which stumbles over this problem

https://bugs.launchpad.net/nevow/+bug/1249946

As you can see from the link in bug report, IE11 is posing as many 
beasts, but in standard mode the UA string is

'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'

HTH, Werner



More information about the Twisted-Python mailing list