This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Alan.Huang
Recipients Alan.Huang, alex, christian.heimes, docs@python, dstufft, janssen
Date 2018-06-29.05:32:23
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1530250345.83.0.56676864532.issue33995@psf.upfronthosting.co.za>
In-reply-to
Content
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.
History
Date User Action Args
2018-06-29 05:32:26Alan.Huangsetrecipients: + Alan.Huang, janssen, christian.heimes, alex, docs@python, dstufft
2018-06-29 05:32:25Alan.Huangsetmessageid: <1530250345.83.0.56676864532.issue33995@psf.upfronthosting.co.za>
2018-06-29 05:32:25Alan.Huanglinkissue33995 messages
2018-06-29 05:32:23Alan.Huangcreate