Issue #16692: The ssl module now supports TLS 1.1 and TLS 1.2. Initial patch by Michele Orrù.
This commit is contained in:
parent
f2c64ed9eb
commit
2463e5fee4
|
@ -26,7 +26,8 @@ probably additional platforms, as long as OpenSSL is installed on that platform.
|
|||
|
||||
Some behavior may be platform dependent, since calls are made to the
|
||||
operating system socket APIs. The installed version of OpenSSL may also
|
||||
cause variations in behavior.
|
||||
cause variations in behavior. For example, TLSv1.1 and TLSv1.2 come with
|
||||
openssl version 1.0.1.
|
||||
|
||||
This section documents the objects and functions in the ``ssl`` module; for more
|
||||
general information about TLS, SSL, and certificates, the reader is referred to
|
||||
|
@ -177,14 +178,16 @@ instead.
|
|||
|
||||
.. table::
|
||||
|
||||
======================== ========= ========= ========== =========
|
||||
*client* / **server** **SSLv2** **SSLv3** **SSLv23** **TLSv1**
|
||||
------------------------ --------- --------- ---------- ---------
|
||||
*SSLv2* yes no yes no
|
||||
*SSLv3* no yes yes no
|
||||
*SSLv23* yes no yes no
|
||||
*TLSv1* no no yes yes
|
||||
======================== ========= ========= ========== =========
|
||||
======================== ========= ========= ========== ========= =========== ===========
|
||||
*client* / **server** **SSLv2** **SSLv3** **SSLv23** **TLSv1** **TLSv1.1** **TLSv1.2**
|
||||
------------------------ --------- --------- ---------- --------- ----------- -----------
|
||||
*SSLv2* yes no yes no no no
|
||||
*SSLv3* no yes yes no no no
|
||||
*SSLv23* yes no yes no no no
|
||||
*TLSv1* no no yes yes no no
|
||||
*TLSv1.1* no no yes no yes no
|
||||
*TLSv1.2* no no yes no no yes
|
||||
======================== ========= ========= ========== ========= =========== ===========
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -401,9 +404,25 @@ Constants
|
|||
|
||||
.. data:: PROTOCOL_TLSv1
|
||||
|
||||
Selects TLS version 1 as the channel encryption protocol. This is the most
|
||||
Selects TLS version 1.0 as the channel encryption protocol.
|
||||
|
||||
.. data:: PROTOCOL_TLSv1_1
|
||||
|
||||
|
||||
Selects TLS version 1.1 as the channel encryption protocol.
|
||||
Available only with openssl version 1.0.1+.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. data:: PROTOCOL_TLSv1_2
|
||||
|
||||
|
||||
Selects TLS version 1.2 as the channel encryption protocol. This is the most
|
||||
modern version, and probably the best choice for maximum protection, if both
|
||||
sides can speak it.
|
||||
Available only with openssl version 1.0.1+.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. data:: OP_ALL
|
||||
|
||||
|
@ -437,6 +456,22 @@ Constants
|
|||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
.. data:: OP_NO_TLSv1_1
|
||||
|
||||
Prevents a TLSv1.1 connection. This option is only applicable in conjunction
|
||||
with :const:`PROTOCOL_SSLv23`. It prevents the peers from choosing TLSv1.1 as
|
||||
the protocol version. Available only with openssl version 1.0.1+.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. data:: OP_NO_TLSv1_2
|
||||
|
||||
Prevents a TLSv1.2 connection. This option is only applicable in conjunction
|
||||
with :const:`PROTOCOL_SSLv23`. It prevents the peers from choosing TLSv1.2 as
|
||||
the protocol version. Available only with openssl version 1.0.1+.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. data:: OP_CIPHER_SERVER_PREFERENCE
|
||||
|
||||
Use the server's cipher ordering preference, rather than the client's.
|
||||
|
|
|
@ -103,6 +103,7 @@ Implementation improvements:
|
|||
Significantly Improved Library Modules:
|
||||
|
||||
* SHA-3 (Keccak) support for :mod:`hashlib`.
|
||||
* TLSv1.1 and TLSv1.2 support for :mod:`ssl`.
|
||||
|
||||
Security improvements:
|
||||
|
||||
|
|
13
Lib/ssl.py
13
Lib/ssl.py
|
@ -52,6 +52,8 @@ PROTOCOL_SSLv2
|
|||
PROTOCOL_SSLv3
|
||||
PROTOCOL_SSLv23
|
||||
PROTOCOL_TLSv1
|
||||
PROTOCOL_TLSv1_1
|
||||
PROTOCOL_TLSv1_2
|
||||
|
||||
The following constants identify various SSL alert message descriptions as per
|
||||
http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6
|
||||
|
@ -110,8 +112,7 @@ _import_symbols('SSL_ERROR_')
|
|||
|
||||
from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN
|
||||
|
||||
from _ssl import (PROTOCOL_SSLv3, PROTOCOL_SSLv23,
|
||||
PROTOCOL_TLSv1)
|
||||
from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1
|
||||
from _ssl import _OPENSSL_API_VERSION
|
||||
|
||||
|
||||
|
@ -128,6 +129,14 @@ except ImportError:
|
|||
else:
|
||||
_PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2"
|
||||
|
||||
try:
|
||||
from _ssl import PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
_PROTOCOL_NAMES[PROTOCOL_TLSv1_1] = "TLSv1.1"
|
||||
_PROTOCOL_NAMES[PROTOCOL_TLSv1_2] = "TLSv1.2"
|
||||
|
||||
from socket import getnameinfo as _getnameinfo
|
||||
from socket import socket, AF_INET, SOCK_STREAM, create_connection
|
||||
import base64 # for DER-to-PEM translation
|
||||
|
|
|
@ -20,13 +20,7 @@ import functools
|
|||
|
||||
ssl = support.import_module("ssl")
|
||||
|
||||
PROTOCOLS = [
|
||||
ssl.PROTOCOL_SSLv3,
|
||||
ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1
|
||||
]
|
||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
||||
PROTOCOLS.append(ssl.PROTOCOL_SSLv2)
|
||||
|
||||
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
|
||||
HOST = support.HOST
|
||||
|
||||
data_file = lambda name: os.path.join(os.path.dirname(__file__), name)
|
||||
|
@ -101,10 +95,6 @@ needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
|
|||
class BasicSocketTests(unittest.TestCase):
|
||||
|
||||
def test_constants(self):
|
||||
#ssl.PROTOCOL_SSLv2
|
||||
ssl.PROTOCOL_SSLv23
|
||||
ssl.PROTOCOL_SSLv3
|
||||
ssl.PROTOCOL_TLSv1
|
||||
ssl.CERT_NONE
|
||||
ssl.CERT_OPTIONAL
|
||||
ssl.CERT_REQUIRED
|
||||
|
@ -396,11 +386,8 @@ class ContextTests(unittest.TestCase):
|
|||
|
||||
@skip_if_broken_ubuntu_ssl
|
||||
def test_constructor(self):
|
||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2)
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
for protocol in PROTOCOLS:
|
||||
ssl.SSLContext(protocol)
|
||||
self.assertRaises(TypeError, ssl.SSLContext)
|
||||
self.assertRaises(ValueError, ssl.SSLContext, -1)
|
||||
self.assertRaises(ValueError, ssl.SSLContext, 42)
|
||||
|
@ -1360,12 +1347,15 @@ else:
|
|||
client_context.options = ssl.OP_ALL | client_options
|
||||
server_context = ssl.SSLContext(server_protocol)
|
||||
server_context.options = ssl.OP_ALL | server_options
|
||||
|
||||
# NOTE: we must enable "ALL" ciphers on the client, otherwise an
|
||||
# SSLv23 client will send an SSLv3 hello (rather than SSLv2)
|
||||
# starting from OpenSSL 1.0.0 (see issue #8322).
|
||||
if client_context.protocol == ssl.PROTOCOL_SSLv23:
|
||||
client_context.set_ciphers("ALL")
|
||||
|
||||
for ctx in (client_context, server_context):
|
||||
ctx.verify_mode = certsreqs
|
||||
# NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client
|
||||
# will send an SSLv3 hello (rather than SSLv2) starting from
|
||||
# OpenSSL 1.0.0 (see issue #8322).
|
||||
ctx.set_ciphers("ALL")
|
||||
ctx.load_cert_chain(CERTFILE)
|
||||
ctx.load_verify_locations(CERTFILE)
|
||||
try:
|
||||
|
@ -1581,6 +1571,49 @@ else:
|
|||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False,
|
||||
client_options=ssl.OP_NO_TLSv1)
|
||||
|
||||
@skip_if_broken_ubuntu_ssl
|
||||
@unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
|
||||
"TLS version 1.1 not supported.")
|
||||
def test_protocol_tlsv1_1(self):
|
||||
"""Connecting to a TLSv1.1 server with various client options.
|
||||
Testing against older TLS versions."""
|
||||
if support.verbose:
|
||||
sys.stdout.write("\n")
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True)
|
||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,
|
||||
client_options=ssl.OP_NO_TLSv1_1)
|
||||
|
||||
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
|
||||
|
||||
|
||||
@skip_if_broken_ubuntu_ssl
|
||||
@unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
|
||||
"TLS version 1.2 not supported.")
|
||||
def test_protocol_tlsv1_2(self):
|
||||
"""Connecting to a TLSv1.2 server with various client options.
|
||||
Testing against older TLS versions."""
|
||||
if support.verbose:
|
||||
sys.stdout.write("\n")
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True,
|
||||
server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
|
||||
client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
|
||||
if hasattr(ssl, 'PROTOCOL_SSLv2'):
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False,
|
||||
client_options=ssl.OP_NO_TLSv1_2)
|
||||
|
||||
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
|
||||
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
|
||||
|
||||
def test_starttls(self):
|
||||
"""Switching from clear text to encrypted and back again."""
|
||||
msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6")
|
||||
|
|
|
@ -297,6 +297,9 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #16692: The ssl module now supports TLS 1.1 and TLS 1.2. Initial
|
||||
patch by Michele Orrù.
|
||||
|
||||
- Issue #17025: multiprocessing: Reduce Queue and SimpleQueue contention.
|
||||
|
||||
- Issue #17536: Add to webbrowser's browser list: www-browser, x-www-browser,
|
||||
|
@ -1005,6 +1008,8 @@ _ Issue #17385: Fix quadratic behavior in threading.Condition. The FIFO
|
|||
- ctypes.call_commethod was removed, since its only usage was in the defunct
|
||||
samples directory.
|
||||
|
||||
- Issue #16692: Added TLSv1.1 and TLSv1.2 support for the ssl modules.
|
||||
|
||||
Extension Modules
|
||||
-----------------
|
||||
|
||||
|
|
124
Modules/_ssl.c
124
Modules/_ssl.c
|
@ -40,6 +40,61 @@
|
|||
|
||||
#endif
|
||||
|
||||
/* Include symbols from _socket module */
|
||||
#include "socketmodule.h"
|
||||
|
||||
static PySocketModule_APIObject PySocketModule;
|
||||
|
||||
#if defined(HAVE_POLL_H)
|
||||
#include <poll.h>
|
||||
#elif defined(HAVE_SYS_POLL_H)
|
||||
#include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
/* Include OpenSSL header files */
|
||||
#include "openssl/rsa.h"
|
||||
#include "openssl/crypto.h"
|
||||
#include "openssl/x509.h"
|
||||
#include "openssl/x509v3.h"
|
||||
#include "openssl/pem.h"
|
||||
#include "openssl/ssl.h"
|
||||
#include "openssl/err.h"
|
||||
#include "openssl/rand.h"
|
||||
|
||||
/* SSL error object */
|
||||
static PyObject *PySSLErrorObject;
|
||||
static PyObject *PySSLZeroReturnErrorObject;
|
||||
static PyObject *PySSLWantReadErrorObject;
|
||||
static PyObject *PySSLWantWriteErrorObject;
|
||||
static PyObject *PySSLSyscallErrorObject;
|
||||
static PyObject *PySSLEOFErrorObject;
|
||||
|
||||
/* Error mappings */
|
||||
static PyObject *err_codes_to_names;
|
||||
static PyObject *err_names_to_codes;
|
||||
static PyObject *lib_codes_to_names;
|
||||
|
||||
struct py_ssl_error_code {
|
||||
const char *mnemonic;
|
||||
int library, reason;
|
||||
};
|
||||
struct py_ssl_library_code {
|
||||
const char *library;
|
||||
int code;
|
||||
};
|
||||
|
||||
/* Include generated data (error codes) */
|
||||
#include "_ssl_data.h"
|
||||
|
||||
/* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1
|
||||
http://www.openssl.org/news/changelog.html
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||||
# define HAVE_TLSv1_2 1
|
||||
#else
|
||||
# define HAVE_TLSv1_2 0
|
||||
#endif
|
||||
|
||||
enum py_ssl_error {
|
||||
/* these mirror ssl.h */
|
||||
PY_SSL_ERROR_NONE,
|
||||
|
@ -73,55 +128,14 @@ enum py_ssl_version {
|
|||
#endif
|
||||
PY_SSL_VERSION_SSL3=1,
|
||||
PY_SSL_VERSION_SSL23,
|
||||
#if HAVE_TLSv1_2
|
||||
PY_SSL_VERSION_TLS1,
|
||||
PY_SSL_VERSION_TLS1_1,
|
||||
PY_SSL_VERSION_TLS1_2
|
||||
#else
|
||||
PY_SSL_VERSION_TLS1
|
||||
};
|
||||
|
||||
struct py_ssl_error_code {
|
||||
const char *mnemonic;
|
||||
int library, reason;
|
||||
};
|
||||
|
||||
struct py_ssl_library_code {
|
||||
const char *library;
|
||||
int code;
|
||||
};
|
||||
|
||||
/* Include symbols from _socket module */
|
||||
#include "socketmodule.h"
|
||||
|
||||
static PySocketModule_APIObject PySocketModule;
|
||||
|
||||
#if defined(HAVE_POLL_H)
|
||||
#include <poll.h>
|
||||
#elif defined(HAVE_SYS_POLL_H)
|
||||
#include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
/* Include OpenSSL header files */
|
||||
#include "openssl/rsa.h"
|
||||
#include "openssl/crypto.h"
|
||||
#include "openssl/x509.h"
|
||||
#include "openssl/x509v3.h"
|
||||
#include "openssl/pem.h"
|
||||
#include "openssl/ssl.h"
|
||||
#include "openssl/err.h"
|
||||
#include "openssl/rand.h"
|
||||
|
||||
/* Include generated data (error codes) */
|
||||
#include "_ssl_data.h"
|
||||
|
||||
/* SSL error object */
|
||||
static PyObject *PySSLErrorObject;
|
||||
static PyObject *PySSLZeroReturnErrorObject;
|
||||
static PyObject *PySSLWantReadErrorObject;
|
||||
static PyObject *PySSLWantWriteErrorObject;
|
||||
static PyObject *PySSLSyscallErrorObject;
|
||||
static PyObject *PySSLEOFErrorObject;
|
||||
|
||||
/* Error mappings */
|
||||
static PyObject *err_codes_to_names;
|
||||
static PyObject *err_names_to_codes;
|
||||
static PyObject *lib_codes_to_names;
|
||||
};
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
|
||||
|
@ -1732,6 +1746,12 @@ context_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
PySSL_BEGIN_ALLOW_THREADS
|
||||
if (proto_version == PY_SSL_VERSION_TLS1)
|
||||
ctx = SSL_CTX_new(TLSv1_method());
|
||||
#if HAVE_TLSv1_2
|
||||
else if (proto_version == PY_SSL_VERSION_TLS1_1)
|
||||
ctx = SSL_CTX_new(TLSv1_1_method());
|
||||
else if (proto_version == PY_SSL_VERSION_TLS1_2)
|
||||
ctx = SSL_CTX_new(TLSv1_2_method());
|
||||
#endif
|
||||
else if (proto_version == PY_SSL_VERSION_SSL3)
|
||||
ctx = SSL_CTX_new(SSLv3_method());
|
||||
#ifndef OPENSSL_NO_SSL2
|
||||
|
@ -3004,6 +3024,12 @@ PyInit__ssl(void)
|
|||
PY_SSL_VERSION_SSL23);
|
||||
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1",
|
||||
PY_SSL_VERSION_TLS1);
|
||||
#if HAVE_TLSv1_2
|
||||
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_1",
|
||||
PY_SSL_VERSION_TLS1_1);
|
||||
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_2",
|
||||
PY_SSL_VERSION_TLS1_2);
|
||||
#endif
|
||||
|
||||
/* protocol options */
|
||||
PyModule_AddIntConstant(m, "OP_ALL",
|
||||
|
@ -3011,6 +3037,10 @@ PyInit__ssl(void)
|
|||
PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2);
|
||||
PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3);
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);
|
||||
#if HAVE_TLSv1_2
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
|
||||
#endif
|
||||
PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE",
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
PyModule_AddIntConstant(m, "OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE);
|
||||
|
|
4
setup.py
4
setup.py
|
@ -786,10 +786,10 @@ class PyBuildExt(build_ext):
|
|||
for line in incfile:
|
||||
m = openssl_ver_re.match(line)
|
||||
if m:
|
||||
openssl_ver = eval(m.group(1))
|
||||
openssl_ver = int(m.group(1), 16)
|
||||
break
|
||||
except IOError as msg:
|
||||
print("IOError while reading opensshv.h:", msg)
|
||||
pass
|
||||
|
||||
#print('openssl_ver = 0x%08x' % openssl_ver)
|
||||
min_openssl_ver = 0x00907000
|
||||
|
|
Loading…
Reference in New Issue