New submission from Alan Huang <[email protected]>:
LibreSSL's implementation of the function used to get the minimum and maximum
SSL versions supported differs from OpenSSL's.
In short, the issue is in the implementations of `SSL_CTX_new` - OpenSSL
initializes variables `ret->{min,max}_proto_version` to 0, while LibreSSL
initializes corresponding variables to those of the `SSL_METHOD` given.
As such, when Python is built with LibreSSL, the default values for an instance
of ssl.SSLContext are, in the case of ssl.SSLContext(), ctx.minimum_version =
<TLSVersion.TLSv1: 769>; ctx.maximum_version = <TLSVersion.TLSv1_2: 771>.
This is NOT what test_ssl.py expects; it expects OpenSSL's behavior of
initializing the version variables to zero, which _ssl.c then translates to
PY_PROTO_{MIN,MAX}IMUM_SUPPORTED -> ssl.TLSVersion.{MIN,MAX}IMUM_SUPPORTED.
Additionally, LibreSSL, when `SSL_CTX_set_{min,max}_proto_version` is called
with `version` equal to zero, explicitly sets the minimum / maximum values
equal to the minimum / maximum values for the `SSL_METHOD` it was called with
(namely, 769/770/771, in the case of `TLS_method()`), not the minimum / maximum
values supported by the library.
I have sent an email to the LibreSSL mailing list asking for clarification on
this point, namely, if this is intended behavior. If it is, there are two ways
that come to mind to work around this behavior. Both ways would only be
necessary if `IS_LIBRESSL`.
1. Skip `test_min_max_version`.
2. Instead of testing that ctx is equal *to* the extremes after it's been set
to one of the extremes, test that it's equal to the actual constants.
There are two ways this could be accomplished as well:
a. Use PY_PROTO_{MIN,MAX}IMUM_AVAILABLE, defined in _ssl.c (this may
require the addition of another call to `PyModule_AddIntConstant` to provide
access to the constant from _ssl). The downside to this approach is that it
assumes that `TLS_method()`, or whatever `SSL_METHOD` test_ssl.py uses has
lower and upper bounds equal to PY_PROTO_{MIN,MAX}IMUM_AVAILABLE, which may not
always be the case.
b. Access and store the values for ctx.{min,max}imum_value on creation,
then reference them after setting.
Either of these approaches would likely also have the benefit of removing
the need for `self.assertIn(ctx.minimum_version, {ssl.TLSVersion.TLSv1_2,
ssl.TLSVersion.TLSv1_3})`.
The test that failed was:
======================================================================
FAIL: test_min_max_version (test.test_ssl.ContextTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/alan/src/cpython/Lib/test/test_ssl.py", line 1066, in
test_min_max_version
ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
AssertionError: <TLSVersion.TLSv1: 769> != <TLSVersion.MINIMUM_SUPPORTED: -2>
Addendum:
I found the documentation for ssl.TLSVersion.{MAX,MIN}IMUM_SUPPORTED confusing
at first - it took me quite a while to realize what the purpose of the
constants were; I would have expected them to contain the maximum and minimum
protocol versions supported by the library; I see why it was phrased that way,
after having boned up on ssl.py, _ssl.c, and OpenSSL/LibreSSL, but think it
could could be made clearer.
----------
assignee: docs@python
components: Documentation, SSL, Tests
messages: 320703
nosy: Alan.Huang, alex, christian.heimes, docs@python, dstufft, janssen
priority: normal
severity: normal
status: open
title: test_min_max_version in test_ssl.py fails when Python is built against
LibreSSL; {min,max}imum_version behavior differs from OpenSSL
type: behavior
versions: Python 3.7
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue33995>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com