Issue 29781: SSLObject.version returns incorrect value before handshake. (original) (raw)
Created on 2017-03-10 10:03 by Lukasa, last changed 2022-04-11 14:58 by admin. This issue is now closed.
Messages (7)
Author: Cory Benfield (Lukasa) *
Date: 2017-03-10 10:03
The SSLObject object from the ssl module has a version() method that is undocumented. A reasonable assumption for the behaviour of that method is that it would follow the behaviour of the same method on SSLSocket(), which has the following documentation:
Return the actual SSL protocol version negotiated by the connection as a string, or None is no secure connection is established. As of this writing, possible return values include "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" and "TLSv1.2". Recent OpenSSL versions may define more return values.
However, SSLObject does not follow that behaviour:
Python 3.6.0 (default, Jan 18 2017, 18:08:34) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin Type "help", "copyright", "credits" or "license" for more information.
import ssl ctx = ssl.create_default_context() in_bio = ssl.MemoryBIO() out_bio = ssl.MemoryBIO() buffers = ctx.wrap_bio(in_bio, out_bio) buffers.version() 'TLSv1.2'
That is, a SSLObject that does not have a TLS session established will incorrectly report that it is using a TLS version. This method should return None in this case.
Author: Cory Benfield (Lukasa) *
Date: 2017-03-10 10:07
A quick test reveals that Python 3.5 is also affected.
Author: Cory Benfield (Lukasa) *
Date: 2017-03-10 10:28
This actually appears to be an outcome of OpenSSL's logic. I've attached a smallish C file that, when run against OpenSSL 1.0.2 on my machine, prints "TLSv1.2".
This seems like a behaviour we'll have to work around in Python to get the outcome we want here.
Author: Cory Benfield (Lukasa) *
Date: 2017-03-10 10:43
I updated the test script to try with a file-descriptor set and OpenSSL returns TLSv1.2 for that one as well. This strongly suggests that OpenSSL's SSL_get_version documentation is somewhat misleading, and that an SSL object will return a version even when it's not connected.
If Python wants to consider this a bug, it will need to track connections state for the SSLObject like it does for the SSLSocket. Otherwise, Python can redocument version for SSLObject to say that it will always return a value.
Author: Christian Heimes (christian.heimes) *
Date: 2017-09-05 22:12
It should be possible to solve the issue w/o tracking the connection state manually. It doesn't work correctly with transparent negotiation -- that is implicit handshake with SSL_write().
SSL_is_init_finished() (https://www.openssl.org/docs/manmaster/man3/SSL_get_state.html) might be the right function.
Author: Christian Heimes (christian.heimes) *
Date: 2017-09-06 04:55
New changeset 6877111648ac3e042ee5d0458cbeb65dd1a84b2d by Christian Heimes in branch 'master': bpo-29781: Fix SSLObject.version before handshake (#3364) https://github.com/python/cpython/commit/6877111648ac3e042ee5d0458cbeb65dd1a84b2d
Author: Christian Heimes (christian.heimes) *
Date: 2017-09-06 13:42
New changeset 6da379bde345926e1f7318ead973767f4d791d3e by Christian Heimes in branch '3.6': [3.6] bpo-29781: Fix SSLObject.version before handshake (GH-3364) (#3381) https://github.com/python/cpython/commit/6da379bde345926e1f7318ead973767f4d791d3e
History
Date
User
Action
Args
2022-04-11 14:58:44
admin
set
github: 73967
2017-09-06 23:39:28
christian.heimes
set
status: open -> closed
type: behavior
resolution: fixed
stage: resolved
2017-09-06 13:47:01
christian.heimes
link
2017-09-06 13:42:33
christian.heimes
set
messages: +
2017-09-06 05:04:46
christian.heimes
set
pull_requests: + <pull%5Frequest3389>
2017-09-06 04:55:43
christian.heimes
set
messages: +
2017-09-05 22:29:23
christian.heimes
set
pull_requests: + <pull%5Frequest3375>
2017-09-05 22:12:30
christian.heimes
set
messages: +
2017-03-10 10:43:45
Lukasa
set
messages: +
2017-03-10 10:29:00
Lukasa
set
files: + test.c
messages: +
2017-03-10 10:07:44
Lukasa
set
messages: +
versions: + Python 3.5
2017-03-10 10:03:04
Lukasa
create