Patchwork [1,of,8,v5] setup: require that Python has TLS 1.1 or TLS 1.2

login
register
mail settings
Submitter Manuel Jacob
Date June 1, 2020, 3:28 a.m.
Message ID <2d2497e32978bc17060f.1590982092@tmp>
Download mbox | patch
Permalink /patch/46438/
State Accepted
Headers show

Comments

Manuel Jacob - June 1, 2020, 3:28 a.m.
# HG changeset patch
# User Manuel Jacob <me@manueljacob.de>
# Date 1590874939 -7200
#      Sat May 30 23:42:19 2020 +0200
# Node ID 2d2497e32978bc17060f5142b45789b449e7d9d3
# Parent  dd7c4a208a4ed6c798330a21b13a349a020c877d
# EXP-Topic require_modern_ssl
setup: require that Python has TLS 1.1 or TLS 1.2

This ensures that Mercurial never downgrades the minimum TLS version from
TLS 1.1+ to TLS 1.0+ and enables us to remove that compatibility code.

It is reasonable to expect that distributions having Python 2.7.9+ or having
backported modern features to the ssl module (which we require) have a OpenSSL
version supporting TLS 1.1 or TLS 1.2, as this is the main reason why
distributions would want to backport these features.

TLS 1.1 and TLS 1.2 are often either both enabled or both not enabled.
However, both can be disabled independently, at least on current Python /
OpenSSL versions.

For the record, I contacted the CPython developers to remark that
unconditionally defining ssl.PROTOCOL_TLSv1_1 / ssl.PROTOCOL_TLSv1_2 is
problematic:
https://github.com/python/cpython/commit/6e8cda91d92da72800d891b2fc2073ecbc134d98#r39569316
Yuya Nishihara - June 1, 2020, 11:32 a.m.
On Mon, 01 Jun 2020 05:28:12 +0200, Manuel Jacob wrote:
> # HG changeset patch
> # User Manuel Jacob <me@manueljacob.de>
> # Date 1590874939 -7200
> #      Sat May 30 23:42:19 2020 +0200
> # Node ID 2d2497e32978bc17060f5142b45789b449e7d9d3
> # Parent  dd7c4a208a4ed6c798330a21b13a349a020c877d
> # EXP-Topic require_modern_ssl
> setup: require that Python has TLS 1.1 or TLS 1.2

Queued 1-6 and 8 for default, thanks.

Next time, please don't send the --intro email, which would be rejected
by server and break email threading.
Manuel Jacob - June 1, 2020, 11:44 a.m.
On 2020-06-01 13:32, Yuya Nishihara wrote:
> On Mon, 01 Jun 2020 05:28:12 +0200, Manuel Jacob wrote:
>> # HG changeset patch
>> # User Manuel Jacob <me@manueljacob.de>
>> # Date 1590874939 -7200
>> #      Sat May 30 23:42:19 2020 +0200
>> # Node ID 2d2497e32978bc17060f5142b45789b449e7d9d3
>> # Parent  dd7c4a208a4ed6c798330a21b13a349a020c877d
>> # EXP-Topic require_modern_ssl
>> setup: require that Python has TLS 1.1 or TLS 1.2
> 
> Queued 1-6 and 8 for default, thanks.
> 
> Next time, please don't send the --intro email, which would be rejected
> by server and break email threading.

Having intro mails worked fine except for the last three, which got 
rejected. Two of these intro mails actually had content and it was 
unfortunate that they didn't get through (in addition to breaking 
threading). I'll not send intro mails until it was analyzed why they 
didn't get through.
Yuya Nishihara - June 1, 2020, 12:40 p.m.
On Mon, 01 Jun 2020 13:44:50 +0200, Manuel Jacob wrote:
> Having intro mails worked fine except for the last three, which got 
> rejected. Two of these intro mails actually had content and it was 
> unfortunate that they didn't get through (in addition to breaking 
> threading). I'll not send intro mails until it was analyzed why they 
> didn't get through.

Intro message is banned because the content will be lost in commit history.
I don't know why it worked for the first two batches. You can configure
patchbomb to not include the PATCH 0 message.

https://www.mercurial-scm.org/wiki/ContributingChanges#Emailing_patches

Patch

diff --git a/relnotes/next b/relnotes/next
--- a/relnotes/next
+++ b/relnotes/next
@@ -7,7 +7,9 @@ 
 == Backwards Compatibility Changes ==
 
 * Mercurial now requires at least Python 2.7.9 or a Python version that
-  backported modern SSL/TLS features (as defined in PEP 466).
+  backported modern SSL/TLS features (as defined in PEP 466), and that Python
+  was compiled against a OpenSSL version supporting TLS 1.1 or TLS 1.2
+  (likely this requires the OpenSSL version to be at least 1.0.1).
 
 
 == Internal API Changes ==
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -98,6 +98,28 @@  features.
     printf(error, file=sys.stderr)
     sys.exit(1)
 
+# ssl.HAS_TLSv1* are preferred to check support but they were added in Python
+# 3.7. Prior to CPython commit 6e8cda91d92da72800d891b2fc2073ecbc134d98
+# (backported to the 3.7 branch), ssl.PROTOCOL_TLSv1_1 / ssl.PROTOCOL_TLSv1_2
+# were defined only if compiled against a OpenSSL version with TLS 1.1 / 1.2
+# support. At the mentioned commit, they were unconditionally defined.
+_notset = object()
+has_tlsv1_1 = getattr(ssl, 'HAS_TLSv1_1', _notset)
+if has_tlsv1_1 is _notset:
+    has_tlsv1_1 = getattr(ssl, 'PROTOCOL_TLSv1_1', _notset) is not _notset
+has_tlsv1_2 = getattr(ssl, 'HAS_TLSv1_2', _notset)
+if has_tlsv1_2 is _notset:
+    has_tlsv1_2 = getattr(ssl, 'PROTOCOL_TLSv1_2', _notset) is not _notset
+if not (has_tlsv1_1 or has_tlsv1_2):
+    error = """
+The `ssl` module does not advertise support for TLS 1.1 or TLS 1.2.
+Please make sure that your Python installation was compiled against an OpenSSL
+version enabling these features (likely this requires the OpenSSL version to
+be at least 1.0.1).
+"""
+    printf(error, file=sys.stderr)
+    sys.exit(1)
+
 if sys.version_info[0] >= 3:
     DYLIB_SUFFIX = sysconfig.get_config_vars()['EXT_SUFFIX']
 else: