summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Paul Calderone <exarkun@twistedmatrix.com>2013-10-06 08:58:04 -0400
committerJean-Paul Calderone <exarkun@twistedmatrix.com>2013-10-06 08:58:04 -0400
commit5c0fd5568efa1ea922f99c74e1e65f0fcdac061c (patch)
tree04ac610a15ee962aa030a2cc92f577be445be02b
parentf7e37e6b2f83f7fd00f7e5aaee9ecc55e349fd87 (diff)
parentd1e969eddee9fe3d970aebdc860f95fccc40230d (diff)
downloadpyopenssl-5c0fd5568efa1ea922f99c74e1e65f0fcdac061c.tar.gz
Add support for negotiating TLSv1_1 or TLSv1_2HEADtrunk
-rw-r--r--ChangeLog5
-rw-r--r--OpenSSL/ssl/context.c30
-rw-r--r--OpenSSL/ssl/context.h2
-rw-r--r--OpenSSL/ssl/ssl.c8
-rw-r--r--OpenSSL/test/test_ssl.py35
-rw-r--r--doc/api/ssl.rst59
6 files changed, 112 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 9fe65c8..7869b91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-10-06 Jean-Paul Calderone <exarkun@twistedmatrix.com>
+
+ * OpenSSL/ssl/context.c: Add support for negotiating TLS v1.1 or
+ v1.2.
+
2013-10-03 Christian Heimes <christian@python.org>
* OpenSSL/crypto/x509.c: Fix an inconsistency in memory management
diff --git a/OpenSSL/ssl/context.c b/OpenSSL/ssl/context.c
index e971c0a..84180b8 100644
--- a/OpenSSL/ssl/context.c
+++ b/OpenSSL/ssl/context.c
@@ -282,9 +282,16 @@ global_tlsext_servername_callback(const SSL *ssl, int *alert, void *arg) {
#ifdef OPENSSL_NO_SSL2
#define SSLv2_METHOD_TEXT ""
#else
-#define SSLv2_METHOD_TEXT "SSLv2_METHOD, "
+#define SSLv2_METHOD_TEXT " SSLv2_METHOD"
#endif
+#ifdef SSL_OP_NO_TLSv1_1
+#define TLSv1_1_METHOD_TEXT " TLSv1_1_METHOD"
+#endif
+
+#ifdef SSL_OP_NO_TLSv1_2
+#define TLSv1_2_METHOD_TEXT " TLSv1_2_METHOD"
+#endif
static char ssl_Context_doc[] = "\n\
Context(method) -> Context instance\n\
@@ -292,11 +299,12 @@ Context(method) -> Context instance\n\
OpenSSL.SSL.Context instances define the parameters for setting up new SSL\n\
connections.\n\
\n\
-:param method: One of " SSLv2_METHOD_TEXT "SSLv3_METHOD, SSLv23_METHOD, or\n\
- TLSv1_METHOD.\n\
+:param method: One of:" SSLv2_METHOD_TEXT " SSLv3_METHOD SSLv23_METHOD TLSv1_METHOD" TLSv1_1_METHOD_TEXT TLSv1_2_METHOD_TEXT "\n\
";
#undef SSLv2_METHOD_TEXT
+#undef TLSv1_1_METHOD_TEXT
+#undef TLSv1_2_METHOD_TEXT
static char ssl_Context_load_verify_locations_doc[] = "\n\
Let SSL know where we can find trusted certificates for the certificate\n\
@@ -1262,6 +1270,22 @@ ssl_Context_init(ssl_ContextObj *self, int i_method) {
case ssl_TLSv1_METHOD:
method = TLSv1_method();
break;
+ case ssl_TLSv1_1_METHOD:
+#ifdef SSL_OP_NO_TLSv1_1
+ method = TLSv1_1_method();
+#else
+ PyErr_SetString(PyExc_ValueError, "TLSv1_1_method not supported by this version of OpenSSL");
+ return NULL;
+#endif
+ break;
+ case ssl_TLSv1_2_METHOD:
+#ifdef SSL_OP_NO_TLSv1_2
+ method = TLSv1_2_method();
+#else
+ PyErr_SetString(PyExc_ValueError, "TLSv1_2_method not supported by this version of OpenSSL");
+ return NULL;
+#endif
+ break;
default:
PyErr_SetString(PyExc_ValueError, "No such protocol");
return NULL;
diff --git a/OpenSSL/ssl/context.h b/OpenSSL/ssl/context.h
index 19b5e9e..989d8f1 100644
--- a/OpenSSL/ssl/context.h
+++ b/OpenSSL/ssl/context.h
@@ -38,6 +38,8 @@ typedef struct {
#define ssl_SSLv3_METHOD (2)
#define ssl_SSLv23_METHOD (3)
#define ssl_TLSv1_METHOD (4)
+#define ssl_TLSv1_1_METHOD (5)
+#define ssl_TLSv1_2_METHOD (6)
#endif
diff --git a/OpenSSL/ssl/ssl.c b/OpenSSL/ssl/ssl.c
index 5725d5d..6b0fd84 100644
--- a/OpenSSL/ssl/ssl.c
+++ b/OpenSSL/ssl/ssl.c
@@ -185,6 +185,8 @@ do { \
PyModule_AddIntConstant(module, "SSLv3_METHOD", ssl_SSLv3_METHOD);
PyModule_AddIntConstant(module, "SSLv23_METHOD", ssl_SSLv23_METHOD);
PyModule_AddIntConstant(module, "TLSv1_METHOD", ssl_TLSv1_METHOD);
+ PyModule_AddIntConstant(module, "TLSv1_1_METHOD", ssl_TLSv1_1_METHOD);
+ PyModule_AddIntConstant(module, "TLSv1_2_METHOD", ssl_TLSv1_2_METHOD);
/* Verify constants */
PyModule_AddIntConstant(module, "VERIFY_NONE", SSL_VERIFY_NONE);
@@ -204,6 +206,12 @@ do { \
PyModule_AddIntConstant(module, "OP_NO_SSLv2", SSL_OP_NO_SSLv2);
PyModule_AddIntConstant(module, "OP_NO_SSLv3", SSL_OP_NO_SSLv3);
PyModule_AddIntConstant(module, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);
+#ifdef SSL_OP_NO_TLSv1_1
+ PyModule_AddIntConstant(module, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
+#endif
+#ifdef SSL_OP_NO_TLSv1_2
+ PyModule_AddIntConstant(module, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
+#endif
/* More SSL option constants */
PyModule_AddIntConstant(module, "OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG);
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index 3e4e3da..9517c9d 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -10,7 +10,7 @@ from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
from sys import platform, version_info
from socket import error, socket
from os import makedirs
-from os.path import join, dirname
+from os.path import join
from unittest import main
from weakref import ref
@@ -22,8 +22,10 @@ from OpenSSL.crypto import dump_certificate, load_certificate
from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
-from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
-from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
+from OpenSSL.SSL import (
+ SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
+ TLSv1_1_METHOD, TLSv1_2_METHOD)
+from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
from OpenSSL.SSL import (
VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
@@ -67,6 +69,11 @@ try:
except ImportError:
MODE_RELEASE_BUFFERS = None
+try:
+ from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
+except ImportError:
+ OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
+
from OpenSSL.SSL import (
SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
SSL_ST_OK, SSL_ST_RENEGOTIATE,
@@ -306,17 +313,23 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_method(self):
"""
:py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
- :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, or :py:obj:`TLSv1_METHOD`.
+ :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
+ :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
"""
- for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
+ methods = [
+ SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
+ for meth in methods:
Context(meth)
- try:
- Context(SSLv2_METHOD)
- except (Error, ValueError):
- # Some versions of OpenSSL have SSLv2, some don't.
- # Difficult to say in advance.
- pass
+
+ maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
+ for meth in maybe:
+ try:
+ Context(meth)
+ except (Error, ValueError):
+ # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
+ # don't. Difficult to say in advance.
+ pass
self.assertRaises(TypeError, Context, "")
self.assertRaises(ValueError, Context, 10)
diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst
index 872cd5a..b506757 100644
--- a/doc/api/ssl.rst
+++ b/doc/api/ssl.rst
@@ -14,9 +14,13 @@ Context, Connection.
SSLv3_METHOD
SSLv23_METHOD
TLSv1_METHOD
+ TLSv1_1_METHOD
+ TLSv1_2_METHOD
These constants represent the different SSL methods to use when creating a
- context object.
+ context object. If the underlying OpenSSL build is missing support for any
+ of these protocols, constructing a :py:class:`Context` using the
+ corresponding :py:const:`*_METHOD` will raise an exception.
.. py:data:: VERIFY_NONE
@@ -35,22 +39,48 @@ Context, Connection.
.. py:data:: OP_SINGLE_DH_USE
- OP_EPHEMERAL_RSA
- OP_NO_SSLv2
+
+ Constant used with :py:meth:`set_options` of Context objects.
+
+ When this option is used, a new key will always be created when using
+ ephemeral Diffie-Hellman.
+
+
+.. py:data:: OP_EPHEMERAL_RSA
+
+ Constant used with :py:meth:`set_options` of Context objects.
+
+ When this option is used, ephemeral RSA keys will always be used when doing
+ RSA operations.
+
+
+.. py:data:: OP_NO_TICKET
+
+ Constant used with :py:meth:`set_options` of Context objects.
+
+ When this option is used, the session ticket extension will not be used.
+
+
+.. py:data:: OP_NO_COMPRESSION
+
+ Constant used with :py:meth:`set_options` of Context objects.
+
+ When this option is used, compression will not be used.
+
+
+.. py:data:: OP_NO_SSLv2
OP_NO_SSLv3
OP_NO_TLSv1
- OP_NO_TICKET
- OP_NO_COMPRESSION
+ OP_NO_TLSv1_1
+ OP_NO_TLSv1_2
Constants used with :py:meth:`set_options` of Context objects.
- :py:const:`OP_SINGLE_DH_USE` means to always create a new key when using
- ephemeral Diffie-Hellman. :py:const:`OP_EPHEMERAL_RSA` means to always use
- ephemeral RSA keys when doing RSA operations. :py:const:`OP_NO_SSLv2`,
- :py:const:`OP_NO_SSLv3` and :py:const:`OP_NO_TLSv1` means to disable those
- specific protocols. This is interesting if you're using e.g.
- :py:const:`SSLv23_METHOD` to get an SSLv2-compatible handshake, but don't want
- to use SSLv2.
+ Each of these options disables one version of the SSL/TLS protocol. This
+ is interesting if you're using e.g. :py:const:`SSLv23_METHOD` to get an
+ SSLv2-compatible handshake, but don't want to use SSLv2. If the underlying
+ OpenSSL build is missing support for any of these protocols, the
+ :py:const:`OP_NO_*` constant may be undefined.
.. py:data:: MODE_NO_COMPRESSION
@@ -69,6 +99,7 @@ Context, Connection.
information to retrieve. See the man page for the :py:func:`SSLeay_version` C
API for details.
+
.. py:data:: SESS_CACHE_OFF
SESS_CACHE_CLIENT
SESS_CACHE_SERVER
@@ -84,6 +115,7 @@ Context, Connection.
.. versionadded:: 0.14
+
.. py:data:: OPENSSL_VERSION_NUMBER
An integer giving the version number of the OpenSSL library used to build this
@@ -109,7 +141,8 @@ Context, Connection.
more SSL connections.
*method* should be :py:const:`SSLv2_METHOD`, :py:const:`SSLv3_METHOD`,
- :py:const:`SSLv23_METHOD` or :py:const:`TLSv1_METHOD`.
+ :py:const:`SSLv23_METHOD`, :py:const:`TLSv1_METHOD`, :py:const:`TLSv1_1_METHOD`,
+ or :py:const:`TLSv1_2_METHOD`.
.. py:class:: Session()