bpo-43669: PEP 644: Require OpenSSL 1.1.1 or newer (GH-23014)

- Remove HAVE_X509_VERIFY_PARAM_SET1_HOST check
- Update hashopenssl to require OpenSSL 1.1.1
- multissltests only OpenSSL > 1.1.0
- ALPN is always supported
- SNI is always supported
- Remove deprecated NPN code. Python wrappers are no-op.
- ECDH is always supported
- Remove OPENSSL_VERSION_1_1 macro
- Remove locking callbacks
- Drop PY_OPENSSL_1_1_API macro
- Drop HAVE_SSL_CTX_CLEAR_OPTIONS macro
- SSL_CTRL_GET_MAX_PROTO_VERSION is always defined now
- security level is always available now
- get_num_tickets is available with TLS 1.3
- X509_V_ERR MISMATCH is always available now
- Always set SSL_MODE_RELEASE_BUFFERS
- X509_V_FLAG_TRUSTED_FIRST is always available
- get_ciphers is always supported
- SSL_CTX_set_keylog_callback is always available
- Update Modules/Setup with static link example
- Mention PEP in whatsnew
- Drop 1.0.2 and 1.1.0 from GHA tests
This commit is contained in:
Christian Heimes 2021-04-17 11:36:35 +02:00 committed by GitHub
parent b467d9a240
commit 39258d3595
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 5144 additions and 8274 deletions

View file

@ -177,7 +177,7 @@ jobs:
strategy:
fail-fast: false
matrix:
openssl_ver: [1.0.2u, 1.1.0l, 1.1.1k, 3.0.0-alpha14]
openssl_ver: [1.1.1k, 3.0.0-alpha14]
env:
OPENSSL_VER: ${{ matrix.openssl_ver }}
MULTISSL_DIR: ${{ github.workspace }}/multissl

View file

@ -135,6 +135,7 @@ some Unices may not have the :program:`env` command, so you may need to hardcode
To use shell commands in your Python scripts, look at the :mod:`subprocess` module.
.. _unix_custom_openssl:
Custom OpenSSL
==============

View file

@ -65,6 +65,7 @@ Summary -- Release highlights
.. PEP-sized items next.
* :pep:`644`, require OpenSSL 1.1.1 or newer
New Features
@ -1438,6 +1439,10 @@ CPython bytecode changes
Build Changes
=============
* :pep:`644`: Python now requires OpenSSL 1.1.1 or newer. OpenSSL 1.0.2 is no
longer supported.
(Contributed by Christian Heimes in :issue:`43669`.)
* The C99 functions :c:func:`snprintf` and :c:func:`vsnprintf` are now required
to build Python.
(Contributed by Victor Stinner in :issue:`36020`.)
@ -1483,7 +1488,6 @@ Build Changes
(Contributed by Christian Heimes in :issue:`43466`.)
C API Changes
=============

View file

@ -909,15 +909,12 @@ def selected_npn_protocol(self):
"""Return the currently selected NPN protocol as a string, or ``None``
if a next protocol was not negotiated or if NPN is not supported by one
of the peers."""
if _ssl.HAS_NPN:
return self._sslobj.selected_npn_protocol()
def selected_alpn_protocol(self):
"""Return the currently selected ALPN protocol as a string, or ``None``
if a next protocol was not negotiated or if ALPN is not supported by one
of the peers."""
if _ssl.HAS_ALPN:
return self._sslobj.selected_alpn_protocol()
return self._sslobj.selected_alpn_protocol()
def cipher(self):
"""Return the currently selected cipher as a 3-tuple ``(name,
@ -1126,10 +1123,7 @@ def getpeercert(self, binary_form=False):
@_sslcopydoc
def selected_npn_protocol(self):
self._checkClosed()
if self._sslobj is None or not _ssl.HAS_NPN:
return None
else:
return self._sslobj.selected_npn_protocol()
return None
@_sslcopydoc
def selected_alpn_protocol(self):

View file

@ -40,7 +40,6 @@
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
HOST = socket_helper.HOST
IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
IS_OPENSSL_1_1_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1)
IS_OPENSSL_3_0_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
@ -270,18 +269,6 @@ def handle_error(prefix):
if support.verbose:
sys.stdout.write(prefix + exc_format)
def can_clear_options():
# 0.9.8m or higher
return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15)
def no_sslv2_implies_sslv3_hello():
# 0.9.7h or higher
return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15)
def have_verify_flags():
# 0.9.8 or higher
return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15)
def _have_secp_curves():
if not ssl.HAS_ECDH:
return False
@ -372,17 +359,15 @@ def test_constants(self):
ssl.OP_SINGLE_DH_USE
if ssl.HAS_ECDH:
ssl.OP_SINGLE_ECDH_USE
if ssl.OPENSSL_VERSION_INFO >= (1, 0):
ssl.OP_NO_COMPRESSION
ssl.OP_NO_COMPRESSION
self.assertIn(ssl.HAS_SNI, {True, False})
self.assertIn(ssl.HAS_ECDH, {True, False})
ssl.OP_NO_SSLv2
ssl.OP_NO_SSLv3
ssl.OP_NO_TLSv1
ssl.OP_NO_TLSv1_3
if ssl.OPENSSL_VERSION_INFO >= (1, 0, 1):
ssl.OP_NO_TLSv1_1
ssl.OP_NO_TLSv1_2
ssl.OP_NO_TLSv1_1
ssl.OP_NO_TLSv1_2
self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
def test_private_init(self):
@ -1161,7 +1146,6 @@ def test_python_ciphers(self):
self.assertNotIn("RC4", name)
self.assertNotIn("3DES", name)
@unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
def test_get_ciphers(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.set_ciphers('AESGCM')
@ -1181,15 +1165,11 @@ def test_options(self):
self.assertEqual(default, ctx.options)
ctx.options |= ssl.OP_NO_TLSv1
self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
if can_clear_options():
ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
self.assertEqual(default, ctx.options)
ctx.options = 0
# Ubuntu has OP_NO_SSLv3 forced on by default
self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
else:
with self.assertRaises(ValueError):
ctx.options = 0
ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
self.assertEqual(default, ctx.options)
ctx.options = 0
# Ubuntu has OP_NO_SSLv3 forced on by default
self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
def test_verify_mode_protocol(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
@ -1327,8 +1307,6 @@ def test_security_level(self):
}
self.assertIn(ctx.security_level, security_level_range)
@unittest.skipUnless(have_verify_flags(),
"verify_flags need OpenSSL > 0.9.8")
def test_verify_flags(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
# default value
@ -1797,7 +1775,6 @@ class MySSLObject(ssl.SSLObject):
obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
self.assertIsInstance(obj, MySSLObject)
@unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1")
def test_num_tickest(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
self.assertEqual(ctx.num_tickets, 2)
@ -2956,8 +2933,6 @@ def test_getpeercert(self):
after = ssl.cert_time_to_seconds(cert['notAfter'])
self.assertLess(before, after)
@unittest.skipUnless(have_verify_flags(),
"verify_flags need OpenSSL > 0.9.8")
def test_crl_check(self):
if support.verbose:
sys.stdout.write("\n")
@ -3859,12 +3834,7 @@ def test_version_basic(self):
self.assertIs(s.version(), None)
self.assertIs(s._sslobj, None)
s.connect((HOST, server.port))
if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
self.assertEqual(s.version(), 'TLSv1.3')
elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
self.assertEqual(s.version(), 'TLSv1.2')
else: # 0.9.8 to 1.0.1
self.assertIn(s.version(), ('TLSv1', 'TLSv1.2'))
self.assertEqual(s.version(), 'TLSv1.3')
self.assertIs(s._sslobj, None)
self.assertIs(s.version(), None)
@ -3966,8 +3936,6 @@ def test_default_ecdh_curve(self):
# explicitly using the 'ECCdraft' cipher alias. Otherwise,
# our default cipher list should prefer ECDH-based ciphers
# automatically.
if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
context.set_ciphers("ECCdraft:ECDH")
with ThreadedEchoServer(context=context) as server:
with context.wrap_socket(socket.socket()) as s:
s.connect((HOST, server.port))
@ -4099,15 +4067,11 @@ def test_ecdh_curve(self):
server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
try:
stats = server_params_test(client_context, server_context,
chatty=True, connectionchatty=True,
sni_name=hostname)
server_params_test(client_context, server_context,
chatty=True, connectionchatty=True,
sni_name=hostname)
except ssl.SSLError:
pass
else:
# OpenSSL 1.0.2 does not fail although it should.
if IS_OPENSSL_1_1_0:
self.fail("mismatch curve did not fail")
self.fail("mismatch curve did not fail")
def test_selected_alpn_protocol(self):
# selected_alpn_protocol() is None unless ALPN is used.
@ -4117,7 +4081,6 @@ def test_selected_alpn_protocol(self):
sni_name=hostname)
self.assertIs(stats['client_alpn_protocol'], None)
@unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
def test_selected_alpn_protocol_if_server_uses_alpn(self):
# selected_alpn_protocol() is None unless ALPN is used by the client.
client_context, server_context, hostname = testing_context()
@ -4127,7 +4090,6 @@ def test_selected_alpn_protocol_if_server_uses_alpn(self):
sni_name=hostname)
self.assertIs(stats['client_alpn_protocol'], None)
@unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
def test_alpn_protocols(self):
server_protocols = ['foo', 'bar', 'milkshake']
protocol_tests = [
@ -4150,22 +4112,17 @@ def test_alpn_protocols(self):
except ssl.SSLError as e:
stats = e
if (expected is None and IS_OPENSSL_1_1_0
and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
# OpenSSL 1.1.0 to 1.1.0e raises handshake error
self.assertIsInstance(stats, ssl.SSLError)
else:
msg = "failed trying %s (s) and %s (c).\n" \
"was expecting %s, but got %%s from the %%s" \
% (str(server_protocols), str(client_protocols),
str(expected))
client_result = stats['client_alpn_protocol']
self.assertEqual(client_result, expected,
msg % (client_result, "client"))
server_result = stats['server_alpn_protocols'][-1] \
if len(stats['server_alpn_protocols']) else 'nothing'
self.assertEqual(server_result, expected,
msg % (server_result, "server"))
msg = "failed trying %s (s) and %s (c).\n" \
"was expecting %s, but got %%s from the %%s" \
% (str(server_protocols), str(client_protocols),
str(expected))
client_result = stats['client_alpn_protocol']
self.assertEqual(client_result, expected,
msg % (client_result, "client"))
server_result = stats['server_alpn_protocols'][-1] \
if len(stats['server_alpn_protocols']) else 'nothing'
self.assertEqual(server_result, expected,
msg % (server_result, "server"))
def test_selected_npn_protocol(self):
# selected_npn_protocol() is None unless NPN is used
@ -4175,31 +4132,8 @@ def test_selected_npn_protocol(self):
sni_name=hostname)
self.assertIs(stats['client_npn_protocol'], None)
@unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
def test_npn_protocols(self):
server_protocols = ['http/1.1', 'spdy/2']
protocol_tests = [
(['http/1.1', 'spdy/2'], 'http/1.1'),
(['spdy/2', 'http/1.1'], 'http/1.1'),
(['spdy/2', 'test'], 'spdy/2'),
(['abc', 'def'], 'abc')
]
for client_protocols, expected in protocol_tests:
client_context, server_context, hostname = testing_context()
server_context.set_npn_protocols(server_protocols)
client_context.set_npn_protocols(client_protocols)
stats = server_params_test(client_context, server_context,
chatty=True, connectionchatty=True,
sni_name=hostname)
msg = "failed trying %s (s) and %s (c).\n" \
"was expecting %s, but got %%s from the %%s" \
% (str(server_protocols), str(client_protocols),
str(expected))
client_result = stats['client_npn_protocol']
self.assertEqual(client_result, expected, msg % (client_result, "client"))
server_result = stats['server_npn_protocols'][-1] \
if len(stats['server_npn_protocols']) else 'nothing'
self.assertEqual(server_result, expected, msg % (server_result, "server"))
assert not ssl.HAS_NPN
def sni_contexts(self):
server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
@ -4369,8 +4303,7 @@ def test_session(self):
self.assertGreater(session.time, 0)
self.assertGreater(session.timeout, 0)
self.assertTrue(session.has_ticket)
if ssl.OPENSSL_VERSION_INFO > (1, 0, 1):
self.assertGreater(session.ticket_lifetime_hint, 0)
self.assertGreater(session.ticket_lifetime_hint, 0)
self.assertFalse(stats['session_reused'])
sess_stat = server_context.session_stats()
self.assertEqual(sess_stat['accept'], 1)

View file

@ -0,0 +1 @@
Implement :pep:`644`. Python now requires OpenSSL 1.1.1 or newer.

View file

@ -207,11 +207,23 @@ _symtable symtablemodule.c
#_socket socketmodule.c
# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
#SSL=/usr/local/ssl
#_ssl _ssl.c \
# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
# -L$(SSL)/lib -lssl -lcrypto
# socket line above, and edit the OPENSSL variable:
# OPENSSL=/path/to/openssl/directory
# _ssl _ssl.c \
# -I$(OPENSSL)/include -L$(OPENSSL)/lib \
# -lssl -lcrypto
#_hashlib _hashopenssl.c \
# -I$(OPENSSL)/include -L$(OPENSSL)/lib \
# -lcrypto
# To statically link OpenSSL:
# _ssl _ssl.c \
# -I$(OPENSSL)/include -L$(OPENSSL)/lib \
# -l:libssl.a -Wl,--exclude-libs,libssl.a \
# -l:libcrypto.a -Wl,--exclude-libs,libcrypto.a
#_hashlib _hashopenssl.c \
# -I$(OPENSSL)/include -L$(OPENSSL)/lib \
# -l:libcrypto.a -Wl,--exclude-libs,libcrypto.a
# The crypt module is now disabled by default because it breaks builds
# on many systems (where -lcrypt is needed), e.g. Linux (I believe).

View file

@ -38,51 +38,12 @@
# error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL"
#endif
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
/* OpenSSL < 1.1.0 */
#define EVP_MD_CTX_new EVP_MD_CTX_create
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
HMAC_CTX *
HMAC_CTX_new(void)
{
HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
if (ctx != NULL) {
memset(ctx, 0, sizeof(HMAC_CTX));
HMAC_CTX_init(ctx);
}
return ctx;
}
void
HMAC_CTX_free(HMAC_CTX *ctx)
{
if (ctx != NULL) {
HMAC_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
}
const EVP_MD *
HMAC_CTX_get_md(const HMAC_CTX *ctx)
{
return ctx->md;
}
#endif
#define MUNCH_SIZE INT_MAX
#ifdef NID_sha3_224
#define PY_OPENSSL_HAS_SCRYPT 1
#define PY_OPENSSL_HAS_SHA3 1
#endif
#if defined(EVP_MD_FLAG_XOF) && defined(NID_shake128)
#define PY_OPENSSL_HAS_SHAKE 1
#endif
#if defined(NID_blake2b512) && !defined(OPENSSL_NO_BLAKE2)
#define PY_OPENSSL_HAS_BLAKE2 1
#endif
static PyModuleDef _hashlibmodule;
@ -1252,8 +1213,7 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name,
return key_obj;
}
#if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)
#define PY_SCRYPT 1
#ifdef PY_OPENSSL_HAS_SCRYPT
/* XXX: Parameters salt, n, r and p should be required keyword-only parameters.
They are optional in the Argument Clinic declaration only due to a
@ -1376,7 +1336,7 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt,
}
return key_obj;
}
#endif
#endif /* PY_OPENSSL_HAS_SCRYPT */
/* Fast HMAC for hmac.digest()
*/
@ -1844,12 +1804,6 @@ hashlib_md_meth_names(PyObject *module)
return 0;
}
/* LibreSSL doesn't support FIPS:
https://marc.info/?l=openbsd-misc&m=139819485423701&w=2
Ted Unangst wrote: "I figured I should mention our current libressl policy
wrt FIPS mode. It's gone and it's not coming back." */
#ifndef LIBRESSL_VERSION_NUMBER
/*[clinic input]
_hashlib.get_fips_mode -> int
@ -1887,7 +1841,6 @@ _hashlib_get_fips_mode_impl(PyObject *module)
return result;
#endif
}
#endif // !LIBRESSL_VERSION_NUMBER
static int
@ -2067,17 +2020,6 @@ hashlib_free(void *m)
}
/* Py_mod_exec functions */
static int
hashlib_openssl_legacy_init(PyObject *module)
{
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
/* Load all digest algorithms and initialize cpuid */
OPENSSL_add_all_algorithms_noconf();
ERR_load_crypto_strings();
#endif
return 0;
}
static int
hashlib_init_evptype(PyObject *module)
{
@ -2200,8 +2142,6 @@ hashlib_exception(PyObject *module)
static PyModuleDef_Slot hashlib_slots[] = {
/* OpenSSL 1.0.2 and LibreSSL */
{Py_mod_exec, hashlib_openssl_legacy_init},
{Py_mod_exec, hashlib_init_evptype},
{Py_mod_exec, hashlib_init_evpxoftype},
{Py_mod_exec, hashlib_init_hmactype},

View file

@ -29,9 +29,9 @@
#define _PySSL_FIX_ERRNO
#define PySSL_BEGIN_ALLOW_THREADS_S(save) \
do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0)
do { (save) = PyEval_SaveThread(); } while(0)
#define PySSL_END_ALLOW_THREADS_S(save) \
do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } _PySSL_FIX_ERRNO; } while (0)
do { PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0)
#define PySSL_BEGIN_ALLOW_THREADS { \
PyThreadState *_save = NULL; \
PySSL_BEGIN_ALLOW_THREADS_S(_save);
@ -62,16 +62,6 @@ static PySocketModule_APIObject PySocketModule;
#include "openssl/bio.h"
#include "openssl/dh.h"
#ifndef HAVE_X509_VERIFY_PARAM_SET1_HOST
# ifdef LIBRESSL_VERSION_NUMBER
# error "LibreSSL is missing X509_VERIFY_PARAM_set1_host(), see https://github.com/libressl-portable/portable/issues/381"
# elif OPENSSL_VERSION_NUMBER > 0x1000200fL
# define HAVE_X509_VERIFY_PARAM_SET1_HOST
# else
# error "libssl is too old and does not support X509_VERIFY_PARAM_set1_host()"
# endif
#endif
#ifndef OPENSSL_THREADS
# error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL"
#endif
@ -142,15 +132,7 @@ static void _PySSLFixErrno(void) {
#include "_ssl_data.h"
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
# define OPENSSL_VERSION_1_1 1
# define PY_OPENSSL_1_1_API 1
#endif
/* OpenSSL API 1.1.0+ does not include version methods. Define the methods
* unless OpenSSL is compiled without the methods. It's the easiest way to
* make 1.0.2, 1.1.0, 1.1.1, and 3.0.0 happy without deprecation warnings.
*/
/* OpenSSL API 1.1.0+ does not include version methods */
#ifndef OPENSSL_NO_TLS1_METHOD
extern const SSL_METHOD *TLSv1_method(void);
#endif
@ -161,129 +143,12 @@ extern const SSL_METHOD *TLSv1_1_method(void);
extern const SSL_METHOD *TLSv1_2_method(void);
#endif
/* LibreSSL 2.7.0 provides necessary OpenSSL 1.1.0 APIs */
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070000fL
# define PY_OPENSSL_1_1_API 1
#endif
/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
* This includes the SSL_set_SSL_CTX() function.
*/
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
# define HAVE_SNI 1
#else
# define HAVE_SNI 0
#endif
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
# define HAVE_ALPN 1
#else
# define HAVE_ALPN 0
#endif
/* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped
* NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility
* reasons. The check for TLSEXT_TYPE_next_proto_neg works with
* OpenSSL 1.0.1+ and LibreSSL.
* OpenSSL 1.1.1-pre1 dropped NPN but still has TLSEXT_TYPE_next_proto_neg.
*/
#ifdef OPENSSL_NO_NEXTPROTONEG
# define HAVE_NPN 0
#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER)
# define HAVE_NPN 0
#elif defined(TLSEXT_TYPE_next_proto_neg)
# define HAVE_NPN 1
#else
# define HAVE_NPN 0
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER)
#define HAVE_OPENSSL_KEYLOG 1
#endif
#ifndef INVALID_SOCKET /* MS defines this */
#define INVALID_SOCKET (-1)
#endif
/* OpenSSL 1.0.2 and LibreSSL needs extra code for locking */
#ifndef OPENSSL_VERSION_1_1
#define HAVE_OPENSSL_CRYPTO_LOCK
#endif
#if defined(OPENSSL_VERSION_1_1) && !defined(OPENSSL_NO_SSL2)
/* OpenSSL 1.1 does not have SSL 2.0 */
#define OPENSSL_NO_SSL2
#endif
#ifndef PY_OPENSSL_1_1_API
/* OpenSSL 1.1 API shims for OpenSSL < 1.1.0 and LibreSSL < 2.7.0 */
#define TLS_method SSLv23_method
#define TLS_client_method SSLv23_client_method
#define TLS_server_method SSLv23_server_method
#define ASN1_STRING_get0_data ASN1_STRING_data
#define X509_get0_notBefore X509_get_notBefore
#define X509_get0_notAfter X509_get_notAfter
#define OpenSSL_version_num SSLeay
#define OpenSSL_version SSLeay_version
#define OPENSSL_VERSION SSLEAY_VERSION
static int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
{
return ne->set;
}
#ifndef OPENSSL_NO_COMP
/* LCOV_EXCL_START */
static int COMP_get_type(const COMP_METHOD *meth)
{
return meth->type;
}
/* LCOV_EXCL_STOP */
#endif
static pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx)
{
return ctx->default_passwd_callback;
}
static void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx)
{
return ctx->default_passwd_callback_userdata;
}
static int X509_OBJECT_get_type(X509_OBJECT *x)
{
return x->type;
}
static X509 *X509_OBJECT_get0_X509(X509_OBJECT *x)
{
return x->data.x509;
}
static int BIO_up_ref(BIO *b)
{
CRYPTO_add(&b->references, 1, CRYPTO_LOCK_BIO);
return 1;
}
static STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *store) {
return store->objs;
}
static int
SSL_SESSION_has_ticket(const SSL_SESSION *s)
{
return (s->tlsext_ticklen > 0) ? 1 : 0;
}
static unsigned long
SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
{
return s->tlsext_tick_lifetime_hint;
}
#endif /* OpenSSL < 1.1.0 or LibreSSL < 2.7.0 */
/* Default cipher suites */
#ifndef PY_SSL_DEFAULT_CIPHERS
@ -395,24 +260,10 @@ enum py_proto_version {
#endif
};
/* serves as a flag to see whether we've initialized the SSL thread support. */
/* 0 means no, greater than 0 means yes */
static unsigned int _ssl_locks_count = 0;
/* SSL socket object */
#define X509_NAME_MAXLEN 256
/* SSL_CTX_clear_options() and SSL_clear_options() were first added in
* OpenSSL 0.9.8m but do not appear in some 0.9.9-dev versions such the
* 0.9.9 from "May 2008" that NetBSD 5.0 uses. */
#if OPENSSL_VERSION_NUMBER >= 0x009080dfL && OPENSSL_VERSION_NUMBER != 0x00909000L
# define HAVE_SSL_CTX_CLEAR_OPTIONS
#else
# undef HAVE_SSL_CTX_CLEAR_OPTIONS
#endif
/* In case of 'tls-unique' it will be 12 bytes for TLS, 36 bytes for
* older SSL, but let's be safe */
@ -422,17 +273,9 @@ static unsigned int _ssl_locks_count = 0;
typedef struct {
PyObject_HEAD
SSL_CTX *ctx;
#if HAVE_NPN
unsigned char *npn_protocols;
int npn_protocols_len;
#endif
#if HAVE_ALPN
unsigned char *alpn_protocols;
unsigned int alpn_protocols_len;
#endif
#ifndef OPENSSL_NO_TLSEXT
PyObject *set_sni_cb;
#endif
int check_hostname;
/* OpenSSL has no API to get hostflags from X509_VERIFY_PARAM* struct.
* We have to maintain our own copy. OpenSSL's hostflags default to 0.
@ -443,10 +286,8 @@ typedef struct {
int post_handshake_auth;
#endif
PyObject *msg_cb;
#ifdef HAVE_OPENSSL_KEYLOG
PyObject *keylog_filename;
BIO *keylog_bio;
#endif
} PySSLContext;
typedef struct {
@ -652,23 +493,18 @@ fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno,
}
switch (verify_code) {
#ifdef X509_V_ERR_HOSTNAME_MISMATCH
/* OpenSSL >= 1.0.2, LibreSSL >= 2.5.3 */
case X509_V_ERR_HOSTNAME_MISMATCH:
verify_obj = PyUnicode_FromFormat(
"Hostname mismatch, certificate is not valid for '%S'.",
sslsock->server_hostname
);
break;
#endif
#ifdef X509_V_ERR_IP_ADDRESS_MISMATCH
case X509_V_ERR_IP_ADDRESS_MISMATCH:
verify_obj = PyUnicode_FromFormat(
"IP address mismatch, certificate is not valid for '%S'.",
sslsock->server_hostname
);
break;
#endif
default:
verify_str = X509_verify_cert_error_string(verify_code);
if (verify_str != NULL) {
@ -1995,7 +1831,6 @@ cipher_to_tuple(const SSL_CIPHER *cipher)
return NULL;
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000UL
static PyObject *
cipher_to_dict(const SSL_CIPHER *cipher)
{
@ -2004,10 +1839,8 @@ cipher_to_dict(const SSL_CIPHER *cipher)
unsigned long cipher_id;
int alg_bits, strength_bits, len;
char buf[512] = {0};
#if OPENSSL_VERSION_1_1
int aead, nid;
const char *skcipher = NULL, *digest = NULL, *kx = NULL, *auth = NULL;
#endif
/* can be NULL */
cipher_name = SSL_CIPHER_get_name(cipher);
@ -2020,7 +1853,6 @@ cipher_to_dict(const SSL_CIPHER *cipher)
buf[len-1] = '\0';
strength_bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
#if OPENSSL_VERSION_1_1
aead = SSL_CIPHER_is_aead(cipher);
nid = SSL_CIPHER_get_cipher_nid(cipher);
skcipher = nid != NID_undef ? OBJ_nid2ln(nid) : NULL;
@ -2030,13 +1862,10 @@ cipher_to_dict(const SSL_CIPHER *cipher)
kx = nid != NID_undef ? OBJ_nid2ln(nid) : NULL;
nid = SSL_CIPHER_get_auth_nid(cipher);
auth = nid != NID_undef ? OBJ_nid2ln(nid) : NULL;
#endif
return Py_BuildValue(
"{sksssssssisi"
#if OPENSSL_VERSION_1_1
"sOssssssss"
#endif
"}",
"id", cipher_id,
"name", cipher_name,
@ -2044,16 +1873,13 @@ cipher_to_dict(const SSL_CIPHER *cipher)
"description", buf,
"strength_bits", strength_bits,
"alg_bits", alg_bits
#if OPENSSL_VERSION_1_1
,"aead", aead ? Py_True : Py_False,
"symmetric", skcipher,
"digest", digest,
"kea", kx,
"auth", auth
#endif
);
}
#endif
/*[clinic input]
_ssl._SSLSocket.shared_ciphers
@ -2124,28 +1950,6 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self)
return PyUnicode_FromString(version);
}
#if HAVE_NPN
/*[clinic input]
_ssl._SSLSocket.selected_npn_protocol
[clinic start generated code]*/
static PyObject *
_ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self)
/*[clinic end generated code: output=b91d494cd207ecf6 input=c28fde139204b826]*/
{
const unsigned char *out;
unsigned int outlen;
SSL_get0_next_proto_negotiated(self->ssl,
&out, &outlen);
if (out == NULL)
Py_RETURN_NONE;
return PyUnicode_FromStringAndSize((char *)out, outlen);
}
#endif
#if HAVE_ALPN
/*[clinic input]
_ssl._SSLSocket.selected_alpn_protocol
[clinic start generated code]*/
@ -2163,7 +1967,6 @@ _ssl__SSLSocket_selected_alpn_protocol_impl(PySSLSocket *self)
Py_RETURN_NONE;
return PyUnicode_FromStringAndSize((char *)out, outlen);
}
#endif
/*[clinic input]
_ssl._SSLSocket.compression
@ -2200,11 +2003,6 @@ static int PySSL_set_context(PySSLSocket *self, PyObject *value,
void *closure) {
if (PyObject_TypeCheck(value, PySSLContext_Type)) {
#if !HAVE_SNI
PyErr_SetString(PyExc_NotImplementedError, "setting a socket's "
"context is not supported by your OpenSSL library");
return -1;
#else
Py_INCREF(value);
Py_SETREF(self->ctx, (PySSLContext *)value);
SSL_set_SSL_CTX(self->ssl, self->ctx->ctx);
@ -2213,7 +2011,6 @@ static int PySSL_set_context(PySSLSocket *self, PyObject *value,
self->ssl,
self->ctx->msg_cb ? _PySSL_msg_callback : NULL
);
#endif
} else {
PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext");
return -1;
@ -2840,8 +2637,6 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self)
#endif
}
#ifdef OPENSSL_VERSION_1_1
static SSL_SESSION*
_ssl_session_dup(SSL_SESSION *session) {
SSL_SESSION *newsession = NULL;
@ -2882,7 +2677,6 @@ _ssl_session_dup(SSL_SESSION *session) {
}
return NULL;
}
#endif
static PyObject *
PySSL_get_session(PySSLSocket *self, void *closure) {
@ -2891,7 +2685,6 @@ PySSL_get_session(PySSLSocket *self, void *closure) {
PySSLSession *pysess;
SSL_SESSION *session;
#ifdef OPENSSL_VERSION_1_1
/* duplicate session as workaround for session bug in OpenSSL 1.1.0,
* https://github.com/openssl/openssl/issues/1550 */
session = SSL_get0_session(self->ssl); /* borrowed reference */
@ -2901,12 +2694,10 @@ PySSL_get_session(PySSLSocket *self, void *closure) {
if ((session = _ssl_session_dup(session)) == NULL) {
return NULL;
}
#else
session = SSL_get1_session(self->ssl);
if (session == NULL) {
Py_RETURN_NONE;
}
#endif
pysess = PyObject_GC_New(PySSLSession, PySSLSession_Type);
if (pysess == NULL) {
SSL_SESSION_free(session);
@ -2925,9 +2716,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
void *closure)
{
PySSLSession *pysess;
#ifdef OPENSSL_VERSION_1_1
SSL_SESSION *session;
#endif
int result;
if (!PySSLSession_Check(value)) {
@ -2951,7 +2740,6 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
"Cannot set session after handshake.");
return -1;
}
#ifdef OPENSSL_VERSION_1_1
/* duplicate session */
if ((session = _ssl_session_dup(pysess->session)) == NULL) {
return -1;
@ -2959,9 +2747,6 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
result = SSL_set_session(self->ssl, session);
/* free duplicate, SSL_set_session() bumps ref count */
SSL_SESSION_free(session);
#else
result = SSL_set_session(self->ssl, pysess->session);
#endif
if (result == 0) {
_setSSLError(NULL, 0, __FILE__, __LINE__);
return -1;
@ -3012,7 +2797,6 @@ static PyMethodDef PySSLMethods[] = {
_SSL__SSLSOCKET_CIPHER_METHODDEF
_SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF
_SSL__SSLSOCKET_VERSION_METHODDEF
_SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF
_SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF
_SSL__SSLSOCKET_COMPRESSION_METHODDEF
_SSL__SSLSOCKET_SHUTDOWN_METHODDEF
@ -3089,9 +2873,6 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
SSL_CTX *ctx = NULL;
X509_VERIFY_PARAM *params;
int result;
#if defined(SSL_MODE_RELEASE_BUFFERS)
unsigned long libver;
#endif
PySSL_BEGIN_ALLOW_THREADS
switch(proto_version) {
@ -3156,19 +2937,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS;
self->protocol = proto_version;
self->msg_cb = NULL;
#ifdef HAVE_OPENSSL_KEYLOG
self->keylog_filename = NULL;
self->keylog_bio = NULL;
#endif
#if HAVE_NPN
self->npn_protocols = NULL;
#endif
#if HAVE_ALPN
self->alpn_protocols = NULL;
#endif
#ifndef OPENSSL_NO_TLSEXT
self->set_sni_cb = NULL;
#endif
/* Don't check host name by default */
if (proto_version == PY_SSL_VERSION_TLS_CLIENT) {
self->check_hostname = 1;
@ -3230,37 +3002,9 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
return NULL;
}
#if defined(SSL_MODE_RELEASE_BUFFERS)
/* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory
usage for no cost at all. However, don't do this for OpenSSL versions
between 1.0.1 and 1.0.1h or 1.0.0 and 1.0.0m, which are affected by CVE
2014-0198. I can't find exactly which beta fixed this CVE, so be
conservative and assume it wasn't fixed until release. We do this check
at runtime to avoid problems from the dynamic linker.
See #25672 for more on this. */
libver = OpenSSL_version_num();
if (!(libver >= 0x10001000UL && libver < 0x1000108fUL) &&
!(libver >= 0x10000000UL && libver < 0x100000dfUL)) {
SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS);
}
#endif
#if !defined(OPENSSL_NO_ECDH) && !defined(OPENSSL_VERSION_1_1)
/* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use
prime256v1 by default. This is Apache mod_ssl's initialization
policy, so we should be safe. OpenSSL 1.1 has it enabled by default.
*/
#if defined(SSL_CTX_set_ecdh_auto)
SSL_CTX_set_ecdh_auto(self->ctx, 1);
#else
{
EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
SSL_CTX_set_tmp_ecdh(self->ctx, key);
EC_KEY_free(key);
}
#endif
#endif
usage for no cost at all. */
SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS);
#define SID_CTX "Python"
SSL_CTX_set_session_id_context(self->ctx, (const unsigned char *) SID_CTX,
@ -3268,11 +3012,9 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
#undef SID_CTX
params = SSL_CTX_get0_param(self->ctx);
#ifdef X509_V_FLAG_TRUSTED_FIRST
/* Improve trust chain building when cross-signed intermediate
certificates are present. See https://bugs.python.org/issue23476. */
X509_VERIFY_PARAM_set_flags(params, X509_V_FLAG_TRUSTED_FIRST);
#endif
X509_VERIFY_PARAM_set_hostflags(params, self->hostflags);
#ifdef TLS1_3_VERSION
@ -3286,9 +3028,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
static int
context_traverse(PySSLContext *self, visitproc visit, void *arg)
{
#ifndef OPENSSL_NO_TLSEXT
Py_VISIT(self->set_sni_cb);
#endif
Py_VISIT(self->msg_cb);
return 0;
}
@ -3296,11 +3036,8 @@ context_traverse(PySSLContext *self, visitproc visit, void *arg)
static int
context_clear(PySSLContext *self)
{
#ifndef OPENSSL_NO_TLSEXT
Py_CLEAR(self->set_sni_cb);
#endif
Py_CLEAR(self->msg_cb);
#ifdef HAVE_OPENSSL_KEYLOG
Py_CLEAR(self->keylog_filename);
if (self->keylog_bio != NULL) {
PySSL_BEGIN_ALLOW_THREADS
@ -3308,7 +3045,6 @@ context_clear(PySSLContext *self)
PySSL_END_ALLOW_THREADS
self->keylog_bio = NULL;
}
#endif
return 0;
}
@ -3320,12 +3056,7 @@ context_dealloc(PySSLContext *self)
PyObject_GC_UnTrack(self);
context_clear(self);
SSL_CTX_free(self->ctx);
#if HAVE_NPN
PyMem_Free(self->npn_protocols);
#endif
#if HAVE_ALPN
PyMem_Free(self->alpn_protocols);
#endif
PyMem_FREE(self->alpn_protocols);
Py_TYPE(self)->tp_free(self);
Py_DECREF(tp);
}
@ -3353,7 +3084,6 @@ _ssl__SSLContext_set_ciphers_impl(PySSLContext *self, const char *cipherlist)
Py_RETURN_NONE;
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000UL
/*[clinic input]
_ssl._SSLContext.get_ciphers
[clinic start generated code]*/
@ -3396,10 +3126,8 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self)
return result;
}
#endif
#if HAVE_NPN || HAVE_ALPN
static int
do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen,
const unsigned char *server_protocols, unsigned int server_protocols_len,
@ -3423,77 +3151,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen,
return SSL_TLSEXT_ERR_OK;
}
#endif
#if HAVE_NPN
/* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */
static int
_advertiseNPN_cb(SSL *s,
const unsigned char **data, unsigned int *len,
void *args)
{
PySSLContext *ssl_ctx = (PySSLContext *) args;
if (ssl_ctx->npn_protocols == NULL) {
*data = (unsigned char *)"";
*len = 0;
} else {
*data = ssl_ctx->npn_protocols;
*len = ssl_ctx->npn_protocols_len;
}
return SSL_TLSEXT_ERR_OK;
}
/* this callback gets passed to SSL_CTX_set_next_proto_select_cb */
static int
_selectNPN_cb(SSL *s,
unsigned char **out, unsigned char *outlen,
const unsigned char *server, unsigned int server_len,
void *args)
{
PySSLContext *ctx = (PySSLContext *)args;
return do_protocol_selection(0, out, outlen, server, server_len,
ctx->npn_protocols, ctx->npn_protocols_len);
}
#endif
/*[clinic input]
_ssl._SSLContext._set_npn_protocols
protos: Py_buffer
/
[clinic start generated code]*/
static PyObject *
_ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self,
Py_buffer *protos)
/*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/
{
#if HAVE_NPN
PyMem_Free(self->npn_protocols);
self->npn_protocols = PyMem_Malloc(protos->len);
if (self->npn_protocols == NULL)
return PyErr_NoMemory();
memcpy(self->npn_protocols, protos->buf, protos->len);
self->npn_protocols_len = (int) protos->len;
/* set both server and client callbacks, because the context can
* be used to create both types of sockets */
SSL_CTX_set_next_protos_advertised_cb(self->ctx,
_advertiseNPN_cb,
self);
SSL_CTX_set_next_proto_select_cb(self->ctx,
_selectNPN_cb,
self);
Py_RETURN_NONE;
#else
PyErr_SetString(PyExc_NotImplementedError,
"The NPN extension requires OpenSSL 1.0.1 or later.");
return NULL;
#endif
}
#if HAVE_ALPN
static int
_selectALPN_cb(SSL *s,
const unsigned char **out, unsigned char *outlen,
@ -3505,7 +3163,6 @@ _selectALPN_cb(SSL *s,
ctx->alpn_protocols, ctx->alpn_protocols_len,
client_protocols, client_protocols_len);
}
#endif
/*[clinic input]
_ssl._SSLContext._set_alpn_protocols
@ -3518,7 +3175,6 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self,
Py_buffer *protos)
/*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/
{
#if HAVE_ALPN
if ((size_t)protos->len > UINT_MAX) {
PyErr_Format(PyExc_OverflowError,
"protocols longer than %u bytes", UINT_MAX);
@ -3537,11 +3193,6 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self,
SSL_CTX_set_alpn_select_cb(self->ctx, _selectALPN_cb, self);
Py_RETURN_NONE;
#else
PyErr_SetString(PyExc_NotImplementedError,
"The ALPN extension requires OpenSSL 1.0.2 or later.");
return NULL;
#endif
}
static PyObject *
@ -3617,9 +3268,6 @@ set_verify_flags(PySSLContext *self, PyObject *arg, void *c)
}
/* Getter and setter for protocol version */
#if defined(SSL_CTRL_GET_MAX_PROTO_VERSION)
static int
set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what)
{
@ -3714,9 +3362,8 @@ set_maximum_version(PySSLContext *self, PyObject *arg, void *c)
{
return set_min_max_proto_version(self, arg, 1);
}
#endif /* SSL_CTRL_GET_MAX_PROTO_VERSION */
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER)
#ifdef TLS1_3_VERSION
static PyObject *
get_num_tickets(PySSLContext *self, void *c)
{
@ -3747,16 +3394,14 @@ set_num_tickets(PySSLContext *self, PyObject *arg, void *c)
PyDoc_STRVAR(PySSLContext_num_tickets_doc,
"Control the number of TLSv1.3 session tickets");
#endif /* OpenSSL 1.1.1 */
#endif /* TLS1_3_VERSION */
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
static PyObject *
get_security_level(PySSLContext *self, void *c)
{
return PyLong_FromLong(SSL_CTX_get_security_level(self->ctx));
}
PyDoc_STRVAR(PySSLContext_security_level_doc, "The current security level");
#endif /* OpenSSL 1.1.0 */
static PyObject *
get_options(PySSLContext *self, void *c)
@ -3774,13 +3419,7 @@ set_options(PySSLContext *self, PyObject *arg, void *c)
clear = opts & ~new_opts;
set = ~opts & new_opts;
if (clear) {
#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS
SSL_CTX_clear_options(self->ctx, clear);
#else
PyErr_SetString(PyExc_ValueError,
"can't clear options before OpenSSL 0.9.8m");
return -1;
#endif
}
if (set)
SSL_CTX_set_options(self->ctx, set);
@ -4468,7 +4107,6 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self)
Py_RETURN_NONE;
}
#ifndef OPENSSL_NO_ECDH
/*[clinic input]
_ssl._SSLContext.set_ecdh_curve
name: object
@ -4503,9 +4141,7 @@ _ssl__SSLContext_set_ecdh_curve(PySSLContext *self, PyObject *name)
EC_KEY_free(key);
Py_RETURN_NONE;
}
#endif
#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT)
static int
_servername_callback(SSL *s, int *al, void *args)
{
@ -4609,7 +4245,6 @@ _servername_callback(SSL *s, int *al, void *args)
PyGILState_Release(gstate);
return ret;
}
#endif
static PyObject *
get_sni_callback(PySSLContext *self, void *c)
@ -4630,7 +4265,6 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
"sni_callback cannot be set on TLS_CLIENT context");
return -1;
}
#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT)
Py_CLEAR(self->set_sni_cb);
if (arg == Py_None) {
SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL);
@ -4648,13 +4282,6 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
SSL_CTX_set_tlsext_servername_arg(self->ctx, self);
}
return 0;
#else
PyErr_SetString(PyExc_NotImplementedError,
"The TLS extension servername callback, "
"SSL_CTX_set_tlsext_servername_callback, "
"is not in the current OpenSSL library.");
return -1;
#endif
}
PyDoc_STRVAR(PySSLContext_sni_callback_doc,
@ -4779,21 +4406,17 @@ static PyGetSetDef context_getsetlist[] = {
(setter) set_check_hostname, NULL},
{"_host_flags", (getter) get_host_flags,
(setter) set_host_flags, NULL},
#if SSL_CTRL_GET_MAX_PROTO_VERSION
{"minimum_version", (getter) get_minimum_version,
(setter) set_minimum_version, NULL},
{"maximum_version", (getter) get_maximum_version,
(setter) set_maximum_version, NULL},
#endif
#ifdef HAVE_OPENSSL_KEYLOG
{"keylog_filename", (getter) _PySSLContext_get_keylog_filename,
(setter) _PySSLContext_set_keylog_filename, NULL},
#endif
{"_msg_callback", (getter) _PySSLContext_get_msg_callback,
(setter) _PySSLContext_set_msg_callback, NULL},
{"sni_callback", (getter) get_sni_callback,
(setter) set_sni_callback, PySSLContext_sni_callback_doc},
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER)
#ifdef TLS1_3_VERSION
{"num_tickets", (getter) get_num_tickets,
(setter) set_num_tickets, PySSLContext_num_tickets_doc},
#endif
@ -4812,10 +4435,8 @@ static PyGetSetDef context_getsetlist[] = {
(setter) set_verify_flags, NULL},
{"verify_mode", (getter) get_verify_mode,
(setter) set_verify_mode, NULL},
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
{"security_level", (getter) get_security_level,
NULL, PySSLContext_security_level_doc},
#endif
{NULL}, /* sentinel */
};
@ -4824,7 +4445,6 @@ static struct PyMethodDef context_methods[] = {
_SSL__SSLCONTEXT__WRAP_BIO_METHODDEF
_SSL__SSLCONTEXT_SET_CIPHERS_METHODDEF
_SSL__SSLCONTEXT__SET_ALPN_PROTOCOLS_METHODDEF
_SSL__SSLCONTEXT__SET_NPN_PROTOCOLS_METHODDEF
_SSL__SSLCONTEXT_LOAD_CERT_CHAIN_METHODDEF
_SSL__SSLCONTEXT_LOAD_DH_PARAMS_METHODDEF
_SSL__SSLCONTEXT_LOAD_VERIFY_LOCATIONS_METHODDEF
@ -5281,11 +4901,7 @@ PySSL_RAND(int len, int pseudo)
if (bytes == NULL)
return NULL;
if (pseudo) {
#ifdef PY_OPENSSL_1_1_API
ok = RAND_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len);
#else
ok = RAND_pseudo_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len);
#endif
if (ok == 0 || ok == 1)
return Py_BuildValue("NO", bytes, ok == 1 ? Py_True : Py_False);
}
@ -5840,92 +5456,6 @@ static PyMethodDef PySSL_methods[] = {
};
#ifdef HAVE_OPENSSL_CRYPTO_LOCK
/* an implementation of OpenSSL threading operations in terms
* of the Python C thread library
* Only used up to 1.0.2. OpenSSL 1.1.0+ has its own locking code.
*/
static PyThread_type_lock *_ssl_locks = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x10000000
/* use new CRYPTO_THREADID API. */
static void
_ssl_threadid_callback(CRYPTO_THREADID *id)
{
CRYPTO_THREADID_set_numeric(id, PyThread_get_thread_ident());
}
#else
/* deprecated CRYPTO_set_id_callback() API. */
static unsigned long
_ssl_thread_id_function (void) {
return PyThread_get_thread_ident();
}
#endif
static void _ssl_thread_locking_function
(int mode, int n, const char *file, int line) {
/* this function is needed to perform locking on shared data
structures. (Note that OpenSSL uses a number of global data
structures that will be implicitly shared whenever multiple
threads use OpenSSL.) Multi-threaded applications will
crash at random if it is not set.
locking_function() must be able to handle up to
CRYPTO_num_locks() different mutex locks. It sets the n-th
lock if mode & CRYPTO_LOCK, and releases it otherwise.
file and line are the file number of the function setting the
lock. They can be useful for debugging.
*/
if ((_ssl_locks == NULL) ||
(n < 0) || ((unsigned)n >= _ssl_locks_count))
return;
if (mode & CRYPTO_LOCK) {
PyThread_acquire_lock(_ssl_locks[n], 1);
} else {
PyThread_release_lock(_ssl_locks[n]);
}
}
static int _setup_ssl_threads(void) {
unsigned int i;
if (_ssl_locks == NULL) {
_ssl_locks_count = CRYPTO_num_locks();
_ssl_locks = PyMem_Calloc(_ssl_locks_count,
sizeof(PyThread_type_lock));
if (_ssl_locks == NULL) {
PyErr_NoMemory();
return 0;
}
for (i = 0; i < _ssl_locks_count; i++) {
_ssl_locks[i] = PyThread_allocate_lock();
if (_ssl_locks[i] == NULL) {
unsigned int j;
for (j = 0; j < i; j++) {
PyThread_free_lock(_ssl_locks[j]);
}
PyMem_Free(_ssl_locks);
return 0;
}
}
CRYPTO_set_locking_callback(_ssl_thread_locking_function);
#if OPENSSL_VERSION_NUMBER >= 0x10000000
CRYPTO_THREADID_set_callback(_ssl_threadid_callback);
#else
CRYPTO_set_id_callback(_ssl_thread_id_function);
#endif
}
return 1;
}
#endif /* HAVE_OPENSSL_CRYPTO_LOCK for OpenSSL < 1.1.0 */
static int
sslmodule_init_types(PyObject *module)
{
@ -6205,10 +5735,8 @@ sslmodule_init_constants(PyObject *m)
X509_V_FLAG_X509_STRICT);
PyModule_AddIntConstant(m, "VERIFY_ALLOW_PROXY_CERTS",
X509_V_FLAG_ALLOW_PROXY_CERTS);
#ifdef X509_V_FLAG_TRUSTED_FIRST
PyModule_AddIntConstant(m, "VERIFY_X509_TRUSTED_FIRST",
X509_V_FLAG_TRUSTED_FIRST);
#endif
/* Alert Descriptions from ssl.h */
/* note RESERVED constants no longer intended for use have been removed */
@ -6365,31 +5893,11 @@ sslmodule_init_constants(PyObject *m)
PyModule_AddObject((m), (key), bool_obj); \
} while (0)
#if HAVE_SNI
addbool(m, "HAS_SNI", 1);
#else
addbool(m, "HAS_SNI", 0);
#endif
addbool(m, "HAS_TLS_UNIQUE", 1);
#ifndef OPENSSL_NO_ECDH
addbool(m, "HAS_ECDH", 1);
#else
addbool(m, "HAS_ECDH", 0);
#endif
#if HAVE_NPN
addbool(m, "HAS_NPN", 1);
#else
addbool(m, "HAS_NPN", 0);
#endif
#if HAVE_ALPN
addbool(m, "HAS_ALPN", 1);
#else
addbool(m, "HAS_ALPN", 0);
#endif
#if defined(SSL2_VERSION) && !defined(OPENSSL_NO_SSL2)
addbool(m, "HAS_SSLv2", 1);
@ -6430,29 +5938,6 @@ sslmodule_init_constants(PyObject *m)
return 0;
}
static int
sslmodule_legacy(PyObject *module)
{
#ifndef OPENSSL_VERSION_1_1
/* Load all algorithms and initialize cpuid */
OPENSSL_add_all_algorithms_noconf();
/* Init OpenSSL */
SSL_load_error_strings();
SSL_library_init();
#endif
#ifdef HAVE_OPENSSL_CRYPTO_LOCK
/* note that this will start threading if not already started */
if (!_setup_ssl_threads()) {
return 0;
}
#elif OPENSSL_VERSION_1_1
/* OpenSSL 1.1.0 builtin thread support is enabled */
_ssl_locks_count++;
#endif
return 0;
}
PyDoc_STRVAR(module_doc,
"Implementation module for SSL socket operations. See the socket module\n\
for documentation.");
@ -6491,8 +5976,6 @@ PyInit__ssl(void)
return NULL;
if (sslmodule_init_versioninfo(m) != 0)
return NULL;
if (sslmodule_legacy(m) != 0)
return NULL;
return m;
}

View file

@ -114,8 +114,6 @@ _PySSLContext_set_msg_callback(PySSLContext *self, PyObject *arg, void *c) {
return 0;
}
#ifdef HAVE_OPENSSL_KEYLOG
static void
_PySSL_keylog_callback(const SSL *ssl, const char *line)
{
@ -219,5 +217,3 @@ _PySSLContext_set_keylog_filename(PySSLContext *self, PyObject *arg, void *c) {
SSL_CTX_set_keylog_callback(self->ctx, _PySSL_keylog_callback);
return 0;
}
#endif

View file

@ -950,7 +950,7 @@ exit:
return return_value;
}
#if (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER))
#if defined(PY_OPENSSL_HAS_SCRYPT)
PyDoc_STRVAR(_hashlib_scrypt__doc__,
"scrypt($module, /, password, *, salt=None, n=None, r=None, p=None,\n"
@ -1068,7 +1068,7 @@ exit:
return return_value;
}
#endif /* (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)) */
#endif /* defined(PY_OPENSSL_HAS_SCRYPT) */
PyDoc_STRVAR(_hashlib_hmac_singleshot__doc__,
"hmac_digest($module, /, key, msg, digest)\n"
@ -1275,8 +1275,6 @@ _hashlib_HMAC_hexdigest(HMACobject *self, PyObject *Py_UNUSED(ignored))
return _hashlib_HMAC_hexdigest_impl(self);
}
#if !defined(LIBRESSL_VERSION_NUMBER)
PyDoc_STRVAR(_hashlib_get_fips_mode__doc__,
"get_fips_mode($module, /)\n"
"--\n"
@ -1312,8 +1310,6 @@ exit:
return return_value;
}
#endif /* !defined(LIBRESSL_VERSION_NUMBER) */
PyDoc_STRVAR(_hashlib_compare_digest__doc__,
"compare_digest($module, a, b, /)\n"
"--\n"
@ -1389,8 +1385,4 @@ exit:
#ifndef _HASHLIB_SCRYPT_METHODDEF
#define _HASHLIB_SCRYPT_METHODDEF
#endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
#ifndef _HASHLIB_GET_FIPS_MODE_METHODDEF
#define _HASHLIB_GET_FIPS_MODE_METHODDEF
#endif /* !defined(_HASHLIB_GET_FIPS_MODE_METHODDEF) */
/*[clinic end generated code: output=980087de1b03ad42 input=a9049054013a1b77]*/
/*[clinic end generated code: output=162369cb9d43f1cc input=a9049054013a1b77]*/

View file

@ -139,29 +139,6 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored))
return _ssl__SSLSocket_version_impl(self);
}
#if (HAVE_NPN)
PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__,
"selected_npn_protocol($self, /)\n"
"--\n"
"\n");
#define _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF \
{"selected_npn_protocol", (PyCFunction)_ssl__SSLSocket_selected_npn_protocol, METH_NOARGS, _ssl__SSLSocket_selected_npn_protocol__doc__},
static PyObject *
_ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self);
static PyObject *
_ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ignored))
{
return _ssl__SSLSocket_selected_npn_protocol_impl(self);
}
#endif /* (HAVE_NPN) */
#if (HAVE_ALPN)
PyDoc_STRVAR(_ssl__SSLSocket_selected_alpn_protocol__doc__,
"selected_alpn_protocol($self, /)\n"
"--\n"
@ -179,8 +156,6 @@ _ssl__SSLSocket_selected_alpn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ig
return _ssl__SSLSocket_selected_alpn_protocol_impl(self);
}
#endif /* (HAVE_ALPN) */
PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__,
"compression($self, /)\n"
"--\n"
@ -452,8 +427,6 @@ exit:
return return_value;
}
#if (OPENSSL_VERSION_NUMBER >= 0x10002000UL)
PyDoc_STRVAR(_ssl__SSLContext_get_ciphers__doc__,
"get_ciphers($self, /)\n"
"--\n"
@ -471,44 +444,6 @@ _ssl__SSLContext_get_ciphers(PySSLContext *self, PyObject *Py_UNUSED(ignored))
return _ssl__SSLContext_get_ciphers_impl(self);
}
#endif /* (OPENSSL_VERSION_NUMBER >= 0x10002000UL) */
PyDoc_STRVAR(_ssl__SSLContext__set_npn_protocols__doc__,
"_set_npn_protocols($self, protos, /)\n"
"--\n"
"\n");
#define _SSL__SSLCONTEXT__SET_NPN_PROTOCOLS_METHODDEF \
{"_set_npn_protocols", (PyCFunction)_ssl__SSLContext__set_npn_protocols, METH_O, _ssl__SSLContext__set_npn_protocols__doc__},
static PyObject *
_ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self,
Py_buffer *protos);
static PyObject *
_ssl__SSLContext__set_npn_protocols(PySSLContext *self, PyObject *arg)
{
PyObject *return_value = NULL;
Py_buffer protos = {NULL, NULL};
if (PyObject_GetBuffer(arg, &protos, PyBUF_SIMPLE) != 0) {
goto exit;
}
if (!PyBuffer_IsContiguous(&protos, 'C')) {
_PyArg_BadArgument("_set_npn_protocols", "argument", "contiguous buffer", arg);
goto exit;
}
return_value = _ssl__SSLContext__set_npn_protocols_impl(self, &protos);
exit:
/* Cleanup for protos */
if (protos.obj) {
PyBuffer_Release(&protos);
}
return return_value;
}
PyDoc_STRVAR(_ssl__SSLContext__set_alpn_protocols__doc__,
"_set_alpn_protocols($self, protos, /)\n"
"--\n"
@ -829,8 +764,6 @@ _ssl__SSLContext_set_default_verify_paths(PySSLContext *self, PyObject *Py_UNUSE
return _ssl__SSLContext_set_default_verify_paths_impl(self);
}
#if !defined(OPENSSL_NO_ECDH)
PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__,
"set_ecdh_curve($self, name, /)\n"
"--\n"
@ -839,8 +772,6 @@ PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__,
#define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF \
{"set_ecdh_curve", (PyCFunction)_ssl__SSLContext_set_ecdh_curve, METH_O, _ssl__SSLContext_set_ecdh_curve__doc__},
#endif /* !defined(OPENSSL_NO_ECDH) */
PyDoc_STRVAR(_ssl__SSLContext_cert_store_stats__doc__,
"cert_store_stats($self, /)\n"
"--\n"
@ -1420,22 +1351,6 @@ exit:
#endif /* defined(_MSC_VER) */
#ifndef _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF
#define _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF
#endif /* !defined(_SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF) */
#ifndef _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF
#define _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF
#endif /* !defined(_SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF) */
#ifndef _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF
#define _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF
#endif /* !defined(_SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF) */
#ifndef _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF
#define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF
#endif /* !defined(_SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF) */
#ifndef _SSL_RAND_EGD_METHODDEF
#define _SSL_RAND_EGD_METHODDEF
#endif /* !defined(_SSL_RAND_EGD_METHODDEF) */
@ -1447,4 +1362,4 @@ exit:
#ifndef _SSL_ENUM_CRLS_METHODDEF
#define _SSL_ENUM_CRLS_METHODDEF
#endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */
/*[clinic end generated code: output=2bb53a80040c9b35 input=a9049054013a1b77]*/
/*[clinic end generated code: output=9468e58904a565a2 input=a9049054013a1b77]*/

View file

@ -43,21 +43,17 @@
log = logging.getLogger("multissl")
OPENSSL_OLD_VERSIONS = [
"1.0.2u",
"1.1.0l",
]
OPENSSL_RECENT_VERSIONS = [
"1.1.1k",
# "3.0.0-alpha14"
"3.0.0-alpha14"
]
LIBRESSL_OLD_VERSIONS = [
"2.9.2",
]
LIBRESSL_RECENT_VERSIONS = [
"3.2.4",
]
# store files in ../multissl

12463
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -5781,42 +5781,6 @@ ac_includes_default="$save_includes_default"
# Check for usable OpenSSL
AX_CHECK_OPENSSL([have_openssl=yes],[have_openssl=no])
if test "$have_openssl" = yes; then
AC_MSG_CHECKING([for X509_VERIFY_PARAM_set1_host in libssl])
save_LIBS="$LIBS"
save_LDFLAGS="$LDFLAGS"
save_CPPFLAGS="$CPPFLAGS"
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
LIBS="$OPENSSL_LIBS $LIBS"
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([
[#include <openssl/x509_vfy.h>]
], [
[X509_VERIFY_PARAM *p = X509_VERIFY_PARAM_new();]
[X509_VERIFY_PARAM_set1_host(p, "localhost", 0);]
[X509_VERIFY_PARAM_set1_ip_asc(p, "127.0.0.1");]
[X509_VERIFY_PARAM_set_hostflags(p, 0);]
])
],
[
ac_cv_has_x509_verify_param_set1_host=yes
],
[
ac_cv_has_x509_verify_param_set1_host=no
])
AC_MSG_RESULT($ac_cv_has_x509_verify_param_set1_host)
if test "$ac_cv_has_x509_verify_param_set1_host" = "yes"; then
AC_DEFINE(HAVE_X509_VERIFY_PARAM_SET1_HOST, 1,
[Define if libssl has X509_VERIFY_PARAM_set1_host and related function])
fi
CPPFLAGS="$save_CPPFLAGS"
LDFLAGS="$save_LDFLAGS"
LIBS="$save_LIBS"
fi
# rpath to libssl and libcrypto
AC_MSG_CHECKING(for --with-openssl-rpath)
AC_ARG_WITH(openssl-rpath,

View file

@ -1356,9 +1356,6 @@
/* Define to 1 if you have the `writev' function. */
#undef HAVE_WRITEV
/* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */
#undef HAVE_X509_VERIFY_PARAM_SET1_HOST
/* Define if the zlib library has inflateCopy */
#undef HAVE_ZLIB_COPY

View file

@ -551,10 +551,7 @@ def print_three_column(lst):
for l in (self.missing, self.failed, self.failed_on_import)):
print()
print("Could not build the ssl module!")
print("Python requires an OpenSSL 1.0.2 or 1.1 compatible "
"libssl with X509_VERIFY_PARAM_set1_host().")
print("LibreSSL 2.6.4 and earlier do not provide the necessary "
"APIs, https://github.com/libressl-portable/portable/issues/381")
print("Python requires a OpenSSL 1.1.1 or newer")
if sysconfig.get_config_var("OPENSSL_LDFLAGS"):
print("Custom linker flags may require --with-openssl-rpath=auto")
print()
@ -2431,13 +2428,13 @@ def split_var(name, sep):
self.missing.extend(['_ssl', '_hashlib'])
return None, None
# OpenSSL 1.0.2 uses Kerberos for KRB5 ciphers
krb5_h = find_file(
'krb5.h', self.inc_dirs,
['/usr/kerberos/include']
self.add(Extension(
'_ssl', ['_ssl.c'],
include_dirs=openssl_includes,
library_dirs=openssl_libdirs,
libraries=openssl_libs,
depends=['socketmodule.h', '_ssl/debughelpers.c'])
)
if krb5_h:
ssl_incs.extend(krb5_h)
if openssl_rpath == 'auto':
runtime_library_dirs = openssl_libdirs[:]
@ -2468,24 +2465,14 @@ def split_var(name, sep):
# don't link OpenSSL shared libraries.
openssl_extension_kwargs["libraries"] = []
if config_vars.get("HAVE_X509_VERIFY_PARAM_SET1_HOST"):
self.add(
Extension(
'_ssl',
['_ssl.c'],
depends=[
'socketmodule.h',
'_ssl/debughelpers.c',
'_ssl_data.h',
'_ssl_data_111.h',
'_ssl_data_300.h',
],
**openssl_extension_kwargs
)
self.add(
Extension(
'_ssl',
['_ssl.c'],
depends=['socketmodule.h', '_ssl/debughelpers.c'],
**openssl_extension_kwargs
)
else:
self.missing.append('_ssl')
)
self.add(
Extension(
'_hashlib',