Merge lp:~exarkun/pyopenssl/tlsv1_1or2 into lp:~exarkun/pyopenssl/trunk

Proposed by Jean-Paul Calderone on 2013-10-04
Status: Merged
Merged at revision: 171
Proposed branch: lp:~exarkun/pyopenssl/tlsv1_1or2
Merge into: lp:~exarkun/pyopenssl/trunk
Diff against target: 275 lines (+109/-29)
5 files modified
OpenSSL/ssl/context.c (+29/-5)
OpenSSL/ssl/context.h (+2/-0)
OpenSSL/ssl/ssl.c (+8/-0)
OpenSSL/test/test_ssl.py (+24/-11)
doc/api/ssl.rst (+46/-13)
To merge this branch: bzr merge lp:~exarkun/pyopenssl/tlsv1_1or2
Reviewer Review Type Date Requested Status
Jean-Paul Calderone Pending
Review via email: mp+189401@code.launchpad.net

Description of the change

Introduces conditional support for TLSv1.1 and TLSv1.2 (conditional on whether the wrapped version of OpenSSL supports them).

To post a comment you must log in.
lp:~exarkun/pyopenssl/tlsv1_1or2 updated on 2013-10-04
172. By Jean-Paul Calderone on 2013-10-04

Oops.

Zooko Wilcox-O'Hearn (zooko) wrote :

I don't understand this code very well, but this looks suspicious:

18 +#ifdef SSL_OP_NO_TLSv1_1
19 +#define TLSv1_2_METHOD_TEXT " TLSv1_2_METHOD"
20 +#endif

Shouldn't it be SSL_OP_NO_TLSv1_2 instead? And if so, and this is a bug, does this mean there isn't an automated test that tries to build pyOpenSSL against some version of OpenSSL that has or doesn't have the #defines necessary to trigger this bug?

Jean-Paul Calderone (exarkun) wrote :

> Shouldn't it be SSL_OP_NO_TLSv1_2 instead?

Almost certainly. Although I don't know whether there are versions of OpenSSL that define one of these (SSL_OP_NO_TLSv1_1, SSL_OP_NO_TLSv1_2) but not the other - so I don't know what the real world consequences of this bug (now fixed) would be.

> does this mean there isn't an automated test that tries to build pyOpenSSL against some version of OpenSSL that has or doesn't have the #defines necessary to trigger this bug?

Yes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'OpenSSL/ssl/context.c'
2--- OpenSSL/ssl/context.c 2012-03-09 23:04:04 +0000
3+++ OpenSSL/ssl/context.c 2013-10-04 19:07:00 +0000
4@@ -282,9 +282,16 @@
5 #ifdef OPENSSL_NO_SSL2
6 #define SSLv2_METHOD_TEXT ""
7 #else
8-#define SSLv2_METHOD_TEXT "SSLv2_METHOD, "
9-#endif
10-
11+#define SSLv2_METHOD_TEXT " SSLv2_METHOD"
12+#endif
13+
14+#ifdef SSL_OP_NO_TLSv1_1
15+#define TLSv1_1_METHOD_TEXT " TLSv1_1_METHOD"
16+#endif
17+
18+#ifdef SSL_OP_NO_TLSv1_2
19+#define TLSv1_2_METHOD_TEXT " TLSv1_2_METHOD"
20+#endif
21
22 static char ssl_Context_doc[] = "\n\
23 Context(method) -> Context instance\n\
24@@ -292,11 +299,12 @@
25 OpenSSL.SSL.Context instances define the parameters for setting up new SSL\n\
26 connections.\n\
27 \n\
28-:param method: One of " SSLv2_METHOD_TEXT "SSLv3_METHOD, SSLv23_METHOD, or\n\
29- TLSv1_METHOD.\n\
30+:param method: One of:" SSLv2_METHOD_TEXT " SSLv3_METHOD SSLv23_METHOD TLSv1_METHOD" TLSv1_1_METHOD_TEXT TLSv1_2_METHOD_TEXT "\n\
31 ";
32
33 #undef SSLv2_METHOD_TEXT
34+#undef TLSv1_1_METHOD_TEXT
35+#undef TLSv1_2_METHOD_TEXT
36
37 static char ssl_Context_load_verify_locations_doc[] = "\n\
38 Let SSL know where we can find trusted certificates for the certificate\n\
39@@ -1262,6 +1270,22 @@
40 case ssl_TLSv1_METHOD:
41 method = TLSv1_method();
42 break;
43+ case ssl_TLSv1_1_METHOD:
44+#ifdef SSL_OP_NO_TLSv1_1
45+ method = TLSv1_1_method();
46+#else
47+ PyErr_SetString(PyExc_ValueError, "TLSv1_1_method not supported by this version of OpenSSL");
48+ return NULL;
49+#endif
50+ break;
51+ case ssl_TLSv1_2_METHOD:
52+#ifdef SSL_OP_NO_TLSv1_2
53+ method = TLSv1_2_method();
54+#else
55+ PyErr_SetString(PyExc_ValueError, "TLSv1_2_method not supported by this version of OpenSSL");
56+ return NULL;
57+#endif
58+ break;
59 default:
60 PyErr_SetString(PyExc_ValueError, "No such protocol");
61 return NULL;
62
63=== modified file 'OpenSSL/ssl/context.h'
64--- OpenSSL/ssl/context.h 2011-05-26 22:47:00 +0000
65+++ OpenSSL/ssl/context.h 2013-10-04 19:07:00 +0000
66@@ -38,6 +38,8 @@
67 #define ssl_SSLv3_METHOD (2)
68 #define ssl_SSLv23_METHOD (3)
69 #define ssl_TLSv1_METHOD (4)
70+#define ssl_TLSv1_1_METHOD (5)
71+#define ssl_TLSv1_2_METHOD (6)
72
73
74 #endif
75
76=== modified file 'OpenSSL/ssl/ssl.c'
77--- OpenSSL/ssl/ssl.c 2012-02-13 14:10:15 +0000
78+++ OpenSSL/ssl/ssl.c 2013-10-04 19:07:00 +0000
79@@ -185,6 +185,8 @@
80 PyModule_AddIntConstant(module, "SSLv3_METHOD", ssl_SSLv3_METHOD);
81 PyModule_AddIntConstant(module, "SSLv23_METHOD", ssl_SSLv23_METHOD);
82 PyModule_AddIntConstant(module, "TLSv1_METHOD", ssl_TLSv1_METHOD);
83+ PyModule_AddIntConstant(module, "TLSv1_1_METHOD", ssl_TLSv1_1_METHOD);
84+ PyModule_AddIntConstant(module, "TLSv1_2_METHOD", ssl_TLSv1_2_METHOD);
85
86 /* Verify constants */
87 PyModule_AddIntConstant(module, "VERIFY_NONE", SSL_VERIFY_NONE);
88@@ -204,6 +206,12 @@
89 PyModule_AddIntConstant(module, "OP_NO_SSLv2", SSL_OP_NO_SSLv2);
90 PyModule_AddIntConstant(module, "OP_NO_SSLv3", SSL_OP_NO_SSLv3);
91 PyModule_AddIntConstant(module, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);
92+#ifdef SSL_OP_NO_TLSv1_1
93+ PyModule_AddIntConstant(module, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
94+#endif
95+#ifdef SSL_OP_NO_TLSv1_2
96+ PyModule_AddIntConstant(module, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
97+#endif
98
99 /* More SSL option constants */
100 PyModule_AddIntConstant(module, "OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG);
101
102=== modified file 'OpenSSL/test/test_ssl.py'
103--- OpenSSL/test/test_ssl.py 2012-03-09 23:27:50 +0000
104+++ OpenSSL/test/test_ssl.py 2013-10-04 19:07:00 +0000
105@@ -10,7 +10,7 @@
106 from sys import platform, version_info
107 from socket import error, socket
108 from os import makedirs
109-from os.path import join, dirname
110+from os.path import join
111 from unittest import main
112 from weakref import ref
113
114@@ -22,8 +22,10 @@
115 from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
116 from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
117 from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
118-from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
119-from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
120+from OpenSSL.SSL import (
121+ SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
122+ TLSv1_1_METHOD, TLSv1_2_METHOD)
123+from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
124 from OpenSSL.SSL import (
125 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
126
127@@ -67,6 +69,11 @@
128 except ImportError:
129 MODE_RELEASE_BUFFERS = None
130
131+try:
132+ from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
133+except ImportError:
134+ OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
135+
136 from OpenSSL.SSL import (
137 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
138 SSL_ST_OK, SSL_ST_RENEGOTIATE,
139@@ -306,17 +313,23 @@
140 def test_method(self):
141 """
142 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
143- :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, or :py:obj:`TLSv1_METHOD`.
144+ :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
145+ :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
146 """
147- for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
148+ methods = [
149+ SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
150+ for meth in methods:
151 Context(meth)
152
153- try:
154- Context(SSLv2_METHOD)
155- except (Error, ValueError):
156- # Some versions of OpenSSL have SSLv2, some don't.
157- # Difficult to say in advance.
158- pass
159+
160+ maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
161+ for meth in maybe:
162+ try:
163+ Context(meth)
164+ except (Error, ValueError):
165+ # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
166+ # don't. Difficult to say in advance.
167+ pass
168
169 self.assertRaises(TypeError, Context, "")
170 self.assertRaises(ValueError, Context, 10)
171
172=== modified file 'doc/api/ssl.rst'
173--- doc/api/ssl.rst 2012-02-16 13:10:04 +0000
174+++ doc/api/ssl.rst 2013-10-04 19:07:00 +0000
175@@ -14,9 +14,13 @@
176 SSLv3_METHOD
177 SSLv23_METHOD
178 TLSv1_METHOD
179+ TLSv1_1_METHOD
180+ TLSv1_2_METHOD
181
182 These constants represent the different SSL methods to use when creating a
183- context object.
184+ context object. If the underlying OpenSSL build is missing support for any
185+ of these protocols, constructing a :py:class:`Context` using the
186+ corresponding :py:const:`*_METHOD` will raise an exception.
187
188
189 .. py:data:: VERIFY_NONE
190@@ -35,22 +39,48 @@
191
192
193 .. py:data:: OP_SINGLE_DH_USE
194- OP_EPHEMERAL_RSA
195- OP_NO_SSLv2
196+
197+ Constant used with :py:meth:`set_options` of Context objects.
198+
199+ When this option is used, a new key will always be created when using
200+ ephemeral Diffie-Hellman.
201+
202+
203+.. py:data:: OP_EPHEMERAL_RSA
204+
205+ Constant used with :py:meth:`set_options` of Context objects.
206+
207+ When this option is used, ephemeral RSA keys will always be used when doing
208+ RSA operations.
209+
210+
211+.. py:data:: OP_NO_TICKET
212+
213+ Constant used with :py:meth:`set_options` of Context objects.
214+
215+ When this option is used, the session ticket extension will not be used.
216+
217+
218+.. py:data:: OP_NO_COMPRESSION
219+
220+ Constant used with :py:meth:`set_options` of Context objects.
221+
222+ When this option is used, compression will not be used.
223+
224+
225+.. py:data:: OP_NO_SSLv2
226 OP_NO_SSLv3
227 OP_NO_TLSv1
228- OP_NO_TICKET
229- OP_NO_COMPRESSION
230+ OP_NO_TLSv1_1
231+ OP_NO_TLSv1_2
232
233 Constants used with :py:meth:`set_options` of Context objects.
234
235- :py:const:`OP_SINGLE_DH_USE` means to always create a new key when using
236- ephemeral Diffie-Hellman. :py:const:`OP_EPHEMERAL_RSA` means to always use
237- ephemeral RSA keys when doing RSA operations. :py:const:`OP_NO_SSLv2`,
238- :py:const:`OP_NO_SSLv3` and :py:const:`OP_NO_TLSv1` means to disable those
239- specific protocols. This is interesting if you're using e.g.
240- :py:const:`SSLv23_METHOD` to get an SSLv2-compatible handshake, but don't want
241- to use SSLv2.
242+ Each of these options disables one version of the SSL/TLS protocol. This
243+ is interesting if you're using e.g. :py:const:`SSLv23_METHOD` to get an
244+ SSLv2-compatible handshake, but don't want to use SSLv2. If the underlying
245+ OpenSSL build is missing support for any of these protocols, the
246+ :py:const:`OP_NO_*` constant may be undefined.
247
248
249 .. py:data:: MODE_NO_COMPRESSION
250@@ -69,6 +99,7 @@
251 information to retrieve. See the man page for the :py:func:`SSLeay_version` C
252 API for details.
253
254+
255 .. py:data:: SESS_CACHE_OFF
256 SESS_CACHE_CLIENT
257 SESS_CACHE_SERVER
258@@ -84,6 +115,7 @@
259
260 .. versionadded:: 0.14
261
262+
263 .. py:data:: OPENSSL_VERSION_NUMBER
264
265 An integer giving the version number of the OpenSSL library used to build this
266@@ -109,7 +141,8 @@
267 more SSL connections.
268
269 *method* should be :py:const:`SSLv2_METHOD`, :py:const:`SSLv3_METHOD`,
270- :py:const:`SSLv23_METHOD` or :py:const:`TLSv1_METHOD`.
271+ :py:const:`SSLv23_METHOD`, :py:const:`TLSv1_METHOD`, :py:const:`TLSv1_1_METHOD`,
272+ or :py:const:`TLSv1_2_METHOD`.
273
274
275 .. py:class:: Session()

Subscribers

People subscribed via source and target branches

to status/vote changes: