diff options
author | Anuj Mittal <anuj.mittal@intel.com> | 2018-09-12 18:16:04 +0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2018-09-13 07:42:28 +0100 |
commit | 3c32b1525ad5ce3ec82542846369547efc62f25a (patch) | |
tree | 1665ff7eea6638f7da98ef803f1c4f4e03150e82 /meta/recipes-devtools/python/python3/0001-Issue-28043-SSLContext-has-improved-default-settings.patch | |
parent | 55f36a4045b44e644887bc4316d6d3aae5d12e22 (diff) | |
download | poky-3c32b1525ad5ce3ec82542846369547efc62f25a.tar.gz |
python3{,-native}: backport openssl 1.1.1 compatibility changes
Backport changes from 3.7/3.6 to fix failing python3 ssl test suite.
Fixes [YOCTO #12919]
(From OE-Core rev: 6c123468b546931de005cf136d98bca6b893b37b)
Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/python/python3/0001-Issue-28043-SSLContext-has-improved-default-settings.patch')
-rw-r--r-- | meta/recipes-devtools/python/python3/0001-Issue-28043-SSLContext-has-improved-default-settings.patch | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python3/0001-Issue-28043-SSLContext-has-improved-default-settings.patch b/meta/recipes-devtools/python/python3/0001-Issue-28043-SSLContext-has-improved-default-settings.patch new file mode 100644 index 0000000000..321b4afa12 --- /dev/null +++ b/meta/recipes-devtools/python/python3/0001-Issue-28043-SSLContext-has-improved-default-settings.patch | |||
@@ -0,0 +1,272 @@ | |||
1 | From 758e7463c104f71b810c8588166747eeab6148d7 Mon Sep 17 00:00:00 2001 | ||
2 | From: Christian Heimes <christian@python.org> | ||
3 | Date: Sat, 10 Sep 2016 22:43:48 +0200 | ||
4 | Subject: [PATCH 1/4] Issue 28043: SSLContext has improved default settings | ||
5 | |||
6 | The options OP_NO_COMPRESSION, OP_CIPHER_SERVER_PREFERENCE, OP_SINGLE_DH_USE, OP_SINGLE_ECDH_USE, OP_NO_SSLv2 (except for PROTOCOL_SSLv2), and OP_NO_SSLv3 (except for PROTOCOL_SSLv3) are set by default. The initial cipher suite list contains only HIGH ciphers, no NULL ciphers and MD5 ciphers (except for PROTOCOL_SSLv2). | ||
7 | |||
8 | Upstream-Status: Backport | ||
9 | [https://github.com/python/cpython/commit/358cfd426ccc0fcd6a7940d306602138e76420ae] | ||
10 | |||
11 | Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> | ||
12 | --- | ||
13 | Doc/library/ssl.rst | 9 ++++++- | ||
14 | Lib/ssl.py | 30 +++++---------------- | ||
15 | Lib/test/test_ssl.py | 62 +++++++++++++++++++++++--------------------- | ||
16 | Modules/_ssl.c | 31 ++++++++++++++++++++++ | ||
17 | 4 files changed, 78 insertions(+), 54 deletions(-) | ||
18 | |||
19 | diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst | ||
20 | index a2f008346b..14f2d68217 100644 | ||
21 | --- a/Doc/library/ssl.rst | ||
22 | +++ b/Doc/library/ssl.rst | ||
23 | @@ -1151,7 +1151,14 @@ to speed up repeated connections from the same clients. | ||
24 | |||
25 | .. versionchanged:: 3.5.3 | ||
26 | |||
27 | - :data:`PROTOCOL_TLS` is the default value. | ||
28 | + The context is created with secure default values. The options | ||
29 | + :data:`OP_NO_COMPRESSION`, :data:`OP_CIPHER_SERVER_PREFERENCE`, | ||
30 | + :data:`OP_SINGLE_DH_USE`, :data:`OP_SINGLE_ECDH_USE`, | ||
31 | + :data:`OP_NO_SSLv2` (except for :data:`PROTOCOL_SSLv2`), | ||
32 | + and :data:`OP_NO_SSLv3` (except for :data:`PROTOCOL_SSLv3`) are | ||
33 | + set by default. The initial cipher suite list contains only ``HIGH`` | ||
34 | + ciphers, no ``NULL`` ciphers and no ``MD5`` ciphers (except for | ||
35 | + :data:`PROTOCOL_SSLv2`). | ||
36 | |||
37 | |||
38 | :class:`SSLContext` objects have the following methods and attributes: | ||
39 | diff --git a/Lib/ssl.py b/Lib/ssl.py | ||
40 | index e1913904f3..4d302a78fa 100644 | ||
41 | --- a/Lib/ssl.py | ||
42 | +++ b/Lib/ssl.py | ||
43 | @@ -446,32 +446,16 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None, | ||
44 | if not isinstance(purpose, _ASN1Object): | ||
45 | raise TypeError(purpose) | ||
46 | |||
47 | + # SSLContext sets OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION, | ||
48 | + # OP_CIPHER_SERVER_PREFERENCE, OP_SINGLE_DH_USE and OP_SINGLE_ECDH_USE | ||
49 | + # by default. | ||
50 | context = SSLContext(PROTOCOL_TLS) | ||
51 | |||
52 | - # SSLv2 considered harmful. | ||
53 | - context.options |= OP_NO_SSLv2 | ||
54 | - | ||
55 | - # SSLv3 has problematic security and is only required for really old | ||
56 | - # clients such as IE6 on Windows XP | ||
57 | - context.options |= OP_NO_SSLv3 | ||
58 | - | ||
59 | - # disable compression to prevent CRIME attacks (OpenSSL 1.0+) | ||
60 | - context.options |= getattr(_ssl, "OP_NO_COMPRESSION", 0) | ||
61 | - | ||
62 | if purpose == Purpose.SERVER_AUTH: | ||
63 | # verify certs and host name in client mode | ||
64 | context.verify_mode = CERT_REQUIRED | ||
65 | context.check_hostname = True | ||
66 | elif purpose == Purpose.CLIENT_AUTH: | ||
67 | - # Prefer the server's ciphers by default so that we get stronger | ||
68 | - # encryption | ||
69 | - context.options |= getattr(_ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) | ||
70 | - | ||
71 | - # Use single use keys in order to improve forward secrecy | ||
72 | - context.options |= getattr(_ssl, "OP_SINGLE_DH_USE", 0) | ||
73 | - context.options |= getattr(_ssl, "OP_SINGLE_ECDH_USE", 0) | ||
74 | - | ||
75 | - # disallow ciphers with known vulnerabilities | ||
76 | context.set_ciphers(_RESTRICTED_SERVER_CIPHERS) | ||
77 | |||
78 | if cafile or capath or cadata: | ||
79 | @@ -497,12 +481,10 @@ def _create_unverified_context(protocol=PROTOCOL_TLS, *, cert_reqs=None, | ||
80 | if not isinstance(purpose, _ASN1Object): | ||
81 | raise TypeError(purpose) | ||
82 | |||
83 | + # SSLContext sets OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION, | ||
84 | + # OP_CIPHER_SERVER_PREFERENCE, OP_SINGLE_DH_USE and OP_SINGLE_ECDH_USE | ||
85 | + # by default. | ||
86 | context = SSLContext(protocol) | ||
87 | - # SSLv2 considered harmful. | ||
88 | - context.options |= OP_NO_SSLv2 | ||
89 | - # SSLv3 has problematic security and is only required for really old | ||
90 | - # clients such as IE6 on Windows XP | ||
91 | - context.options |= OP_NO_SSLv3 | ||
92 | |||
93 | if cert_reqs is not None: | ||
94 | context.verify_mode = cert_reqs | ||
95 | diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py | ||
96 | index ffb7314f57..f91af7bd05 100644 | ||
97 | --- a/Lib/test/test_ssl.py | ||
98 | +++ b/Lib/test/test_ssl.py | ||
99 | @@ -73,6 +73,12 @@ NULLBYTECERT = data_file("nullbytecert.pem") | ||
100 | DHFILE = data_file("dh1024.pem") | ||
101 | BYTES_DHFILE = os.fsencode(DHFILE) | ||
102 | |||
103 | +# Not defined in all versions of OpenSSL | ||
104 | +OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0) | ||
105 | +OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0) | ||
106 | +OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0) | ||
107 | +OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) | ||
108 | + | ||
109 | |||
110 | def handle_error(prefix): | ||
111 | exc_format = ' '.join(traceback.format_exception(*sys.exc_info())) | ||
112 | @@ -839,8 +845,9 @@ class ContextTests(unittest.TestCase): | ||
113 | ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | ||
114 | # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value | ||
115 | default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3) | ||
116 | - if not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0): | ||
117 | - default |= ssl.OP_NO_COMPRESSION | ||
118 | + # SSLContext also enables these by default | ||
119 | + default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE | | ||
120 | + OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE) | ||
121 | self.assertEqual(default, ctx.options) | ||
122 | ctx.options |= ssl.OP_NO_TLSv1 | ||
123 | self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options) | ||
124 | @@ -1205,16 +1212,29 @@ class ContextTests(unittest.TestCase): | ||
125 | stats["x509"] += 1 | ||
126 | self.assertEqual(ctx.cert_store_stats(), stats) | ||
127 | |||
128 | + def _assert_context_options(self, ctx): | ||
129 | + self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
130 | + if OP_NO_COMPRESSION != 0: | ||
131 | + self.assertEqual(ctx.options & OP_NO_COMPRESSION, | ||
132 | + OP_NO_COMPRESSION) | ||
133 | + if OP_SINGLE_DH_USE != 0: | ||
134 | + self.assertEqual(ctx.options & OP_SINGLE_DH_USE, | ||
135 | + OP_SINGLE_DH_USE) | ||
136 | + if OP_SINGLE_ECDH_USE != 0: | ||
137 | + self.assertEqual(ctx.options & OP_SINGLE_ECDH_USE, | ||
138 | + OP_SINGLE_ECDH_USE) | ||
139 | + if OP_CIPHER_SERVER_PREFERENCE != 0: | ||
140 | + self.assertEqual(ctx.options & OP_CIPHER_SERVER_PREFERENCE, | ||
141 | + OP_CIPHER_SERVER_PREFERENCE) | ||
142 | + | ||
143 | def test_create_default_context(self): | ||
144 | ctx = ssl.create_default_context() | ||
145 | + | ||
146 | self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) | ||
147 | self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) | ||
148 | self.assertTrue(ctx.check_hostname) | ||
149 | - self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
150 | - self.assertEqual( | ||
151 | - ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), | ||
152 | - getattr(ssl, "OP_NO_COMPRESSION", 0), | ||
153 | - ) | ||
154 | + self._assert_context_options(ctx) | ||
155 | + | ||
156 | |||
157 | with open(SIGNING_CA) as f: | ||
158 | cadata = f.read() | ||
159 | @@ -1222,40 +1242,24 @@ class ContextTests(unittest.TestCase): | ||
160 | cadata=cadata) | ||
161 | self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) | ||
162 | self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) | ||
163 | - self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
164 | - self.assertEqual( | ||
165 | - ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), | ||
166 | - getattr(ssl, "OP_NO_COMPRESSION", 0), | ||
167 | - ) | ||
168 | + self._assert_context_options(ctx) | ||
169 | |||
170 | ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) | ||
171 | self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) | ||
172 | self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) | ||
173 | - self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
174 | - self.assertEqual( | ||
175 | - ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), | ||
176 | - getattr(ssl, "OP_NO_COMPRESSION", 0), | ||
177 | - ) | ||
178 | - self.assertEqual( | ||
179 | - ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0), | ||
180 | - getattr(ssl, "OP_SINGLE_DH_USE", 0), | ||
181 | - ) | ||
182 | - self.assertEqual( | ||
183 | - ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0), | ||
184 | - getattr(ssl, "OP_SINGLE_ECDH_USE", 0), | ||
185 | - ) | ||
186 | + self._assert_context_options(ctx) | ||
187 | |||
188 | def test__create_stdlib_context(self): | ||
189 | ctx = ssl._create_stdlib_context() | ||
190 | self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) | ||
191 | self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) | ||
192 | self.assertFalse(ctx.check_hostname) | ||
193 | - self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
194 | + self._assert_context_options(ctx) | ||
195 | |||
196 | ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1) | ||
197 | self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1) | ||
198 | self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) | ||
199 | - self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
200 | + self._assert_context_options(ctx) | ||
201 | |||
202 | ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1, | ||
203 | cert_reqs=ssl.CERT_REQUIRED, | ||
204 | @@ -1263,12 +1267,12 @@ class ContextTests(unittest.TestCase): | ||
205 | self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1) | ||
206 | self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) | ||
207 | self.assertTrue(ctx.check_hostname) | ||
208 | - self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
209 | + self._assert_context_options(ctx) | ||
210 | |||
211 | ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH) | ||
212 | self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) | ||
213 | self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) | ||
214 | - self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) | ||
215 | + self._assert_context_options(ctx) | ||
216 | |||
217 | def test_check_hostname(self): | ||
218 | ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | ||
219 | diff --git a/Modules/_ssl.c b/Modules/_ssl.c | ||
220 | index 86482677ae..0d5c121d2c 100644 | ||
221 | --- a/Modules/_ssl.c | ||
222 | +++ b/Modules/_ssl.c | ||
223 | @@ -2330,6 +2330,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) | ||
224 | PySSLContext *self; | ||
225 | long options; | ||
226 | SSL_CTX *ctx = NULL; | ||
227 | + int result; | ||
228 | #if defined(SSL_MODE_RELEASE_BUFFERS) | ||
229 | unsigned long libver; | ||
230 | #endif | ||
231 | @@ -2393,8 +2394,38 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) | ||
232 | options |= SSL_OP_NO_SSLv2; | ||
233 | if (proto_version != PY_SSL_VERSION_SSL3) | ||
234 | options |= SSL_OP_NO_SSLv3; | ||
235 | + /* Minimal security flags for server and client side context. | ||
236 | + * Client sockets ignore server-side parameters. */ | ||
237 | +#ifdef SSL_OP_NO_COMPRESSION | ||
238 | + options |= SSL_OP_NO_COMPRESSION; | ||
239 | +#endif | ||
240 | +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE | ||
241 | + options |= SSL_OP_CIPHER_SERVER_PREFERENCE; | ||
242 | +#endif | ||
243 | +#ifdef SSL_OP_SINGLE_DH_USE | ||
244 | + options |= SSL_OP_SINGLE_DH_USE; | ||
245 | +#endif | ||
246 | +#ifdef SSL_OP_SINGLE_ECDH_USE | ||
247 | + options |= SSL_OP_SINGLE_ECDH_USE; | ||
248 | +#endif | ||
249 | SSL_CTX_set_options(self->ctx, options); | ||
250 | |||
251 | + /* A bare minimum cipher list without completly broken cipher suites. | ||
252 | + * It's far from perfect but gives users a better head start. */ | ||
253 | + if (proto_version != PY_SSL_VERSION_SSL2) { | ||
254 | + result = SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!eNULL:!MD5"); | ||
255 | + } else { | ||
256 | + /* SSLv2 needs MD5 */ | ||
257 | + result = SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!eNULL"); | ||
258 | + } | ||
259 | + if (result == 0) { | ||
260 | + Py_DECREF(self); | ||
261 | + ERR_clear_error(); | ||
262 | + PyErr_SetString(PySSLErrorObject, | ||
263 | + "No cipher can be selected."); | ||
264 | + return NULL; | ||
265 | + } | ||
266 | + | ||
267 | #if defined(SSL_MODE_RELEASE_BUFFERS) | ||
268 | /* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory | ||
269 | usage for no cost at all. However, don't do this for OpenSSL versions | ||
270 | -- | ||
271 | 2.17.1 | ||
272 | |||