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: strategy:
fail-fast: false fail-fast: false
matrix: 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: env:
OPENSSL_VER: ${{ matrix.openssl_ver }} OPENSSL_VER: ${{ matrix.openssl_ver }}
MULTISSL_DIR: ${{ github.workspace }}/multissl 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. To use shell commands in your Python scripts, look at the :mod:`subprocess` module.
.. _unix_custom_openssl:
Custom OpenSSL Custom OpenSSL
============== ==============

View file

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

View file

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

View file

@ -40,7 +40,6 @@ Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
HOST = socket_helper.HOST HOST = socket_helper.HOST
IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL') 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_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) 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') PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
@ -270,18 +269,6 @@ def handle_error(prefix):
if support.verbose: if support.verbose:
sys.stdout.write(prefix + exc_format) 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(): def _have_secp_curves():
if not ssl.HAS_ECDH: if not ssl.HAS_ECDH:
return False return False
@ -372,17 +359,15 @@ class BasicSocketTests(unittest.TestCase):
ssl.OP_SINGLE_DH_USE ssl.OP_SINGLE_DH_USE
if ssl.HAS_ECDH: if ssl.HAS_ECDH:
ssl.OP_SINGLE_ECDH_USE 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_SNI, {True, False})
self.assertIn(ssl.HAS_ECDH, {True, False}) self.assertIn(ssl.HAS_ECDH, {True, False})
ssl.OP_NO_SSLv2 ssl.OP_NO_SSLv2
ssl.OP_NO_SSLv3 ssl.OP_NO_SSLv3
ssl.OP_NO_TLSv1 ssl.OP_NO_TLSv1
ssl.OP_NO_TLSv1_3 ssl.OP_NO_TLSv1_3
if ssl.OPENSSL_VERSION_INFO >= (1, 0, 1): ssl.OP_NO_TLSv1_1
ssl.OP_NO_TLSv1_1 ssl.OP_NO_TLSv1_2
ssl.OP_NO_TLSv1_2
self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23) self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
def test_private_init(self): def test_private_init(self):
@ -1161,7 +1146,6 @@ class ContextTests(unittest.TestCase):
self.assertNotIn("RC4", name) self.assertNotIn("RC4", name)
self.assertNotIn("3DES", name) self.assertNotIn("3DES", name)
@unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old')
def test_get_ciphers(self): def test_get_ciphers(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.set_ciphers('AESGCM') ctx.set_ciphers('AESGCM')
@ -1181,15 +1165,11 @@ class ContextTests(unittest.TestCase):
self.assertEqual(default, ctx.options) self.assertEqual(default, ctx.options)
ctx.options |= ssl.OP_NO_TLSv1 ctx.options |= ssl.OP_NO_TLSv1
self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options) self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
if can_clear_options(): ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1) self.assertEqual(default, ctx.options)
self.assertEqual(default, ctx.options) ctx.options = 0
ctx.options = 0 # Ubuntu has OP_NO_SSLv3 forced on by default
# Ubuntu has OP_NO_SSLv3 forced on by default self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
else:
with self.assertRaises(ValueError):
ctx.options = 0
def test_verify_mode_protocol(self): def test_verify_mode_protocol(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
@ -1327,8 +1307,6 @@ class ContextTests(unittest.TestCase):
} }
self.assertIn(ctx.security_level, security_level_range) 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): def test_verify_flags(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
# default value # default value
@ -1797,7 +1775,6 @@ class ContextTests(unittest.TestCase):
obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO()) obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO())
self.assertIsInstance(obj, MySSLObject) self.assertIsInstance(obj, MySSLObject)
@unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1")
def test_num_tickest(self): def test_num_tickest(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
self.assertEqual(ctx.num_tickets, 2) self.assertEqual(ctx.num_tickets, 2)
@ -2956,8 +2933,6 @@ class ThreadedTests(unittest.TestCase):
after = ssl.cert_time_to_seconds(cert['notAfter']) after = ssl.cert_time_to_seconds(cert['notAfter'])
self.assertLess(before, after) self.assertLess(before, after)
@unittest.skipUnless(have_verify_flags(),
"verify_flags need OpenSSL > 0.9.8")
def test_crl_check(self): def test_crl_check(self):
if support.verbose: if support.verbose:
sys.stdout.write("\n") sys.stdout.write("\n")
@ -3859,12 +3834,7 @@ class ThreadedTests(unittest.TestCase):
self.assertIs(s.version(), None) self.assertIs(s.version(), None)
self.assertIs(s._sslobj, None) self.assertIs(s._sslobj, None)
s.connect((HOST, server.port)) s.connect((HOST, server.port))
if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'): self.assertEqual(s.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.assertIs(s._sslobj, None) self.assertIs(s._sslobj, None)
self.assertIs(s.version(), None) self.assertIs(s.version(), None)
@ -3966,8 +3936,6 @@ class ThreadedTests(unittest.TestCase):
# explicitly using the 'ECCdraft' cipher alias. Otherwise, # explicitly using the 'ECCdraft' cipher alias. Otherwise,
# our default cipher list should prefer ECDH-based ciphers # our default cipher list should prefer ECDH-based ciphers
# automatically. # automatically.
if ssl.OPENSSL_VERSION_INFO < (1, 0, 0):
context.set_ciphers("ECCdraft:ECDH")
with ThreadedEchoServer(context=context) as server: with ThreadedEchoServer(context=context) as server:
with context.wrap_socket(socket.socket()) as s: with context.wrap_socket(socket.socket()) as s:
s.connect((HOST, server.port)) s.connect((HOST, server.port))
@ -4099,15 +4067,11 @@ class ThreadedTests(unittest.TestCase):
server_context.set_ciphers("ECDHE:!eNULL:!aNULL") server_context.set_ciphers("ECDHE:!eNULL:!aNULL")
server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
try: try:
stats = server_params_test(client_context, server_context, server_params_test(client_context, server_context,
chatty=True, connectionchatty=True, chatty=True, connectionchatty=True,
sni_name=hostname) sni_name=hostname)
except ssl.SSLError: except ssl.SSLError:
pass self.fail("mismatch curve did not fail")
else:
# OpenSSL 1.0.2 does not fail although it should.
if IS_OPENSSL_1_1_0:
self.fail("mismatch curve did not fail")
def test_selected_alpn_protocol(self): def test_selected_alpn_protocol(self):
# selected_alpn_protocol() is None unless ALPN is used. # selected_alpn_protocol() is None unless ALPN is used.
@ -4117,7 +4081,6 @@ class ThreadedTests(unittest.TestCase):
sni_name=hostname) sni_name=hostname)
self.assertIs(stats['client_alpn_protocol'], None) 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): def test_selected_alpn_protocol_if_server_uses_alpn(self):
# selected_alpn_protocol() is None unless ALPN is used by the client. # selected_alpn_protocol() is None unless ALPN is used by the client.
client_context, server_context, hostname = testing_context() client_context, server_context, hostname = testing_context()
@ -4127,7 +4090,6 @@ class ThreadedTests(unittest.TestCase):
sni_name=hostname) sni_name=hostname)
self.assertIs(stats['client_alpn_protocol'], None) self.assertIs(stats['client_alpn_protocol'], None)
@unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
def test_alpn_protocols(self): def test_alpn_protocols(self):
server_protocols = ['foo', 'bar', 'milkshake'] server_protocols = ['foo', 'bar', 'milkshake']
protocol_tests = [ protocol_tests = [
@ -4150,22 +4112,17 @@ class ThreadedTests(unittest.TestCase):
except ssl.SSLError as e: except ssl.SSLError as e:
stats = e stats = e
if (expected is None and IS_OPENSSL_1_1_0 msg = "failed trying %s (s) and %s (c).\n" \
and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)): "was expecting %s, but got %%s from the %%s" \
# OpenSSL 1.1.0 to 1.1.0e raises handshake error % (str(server_protocols), str(client_protocols),
self.assertIsInstance(stats, ssl.SSLError) str(expected))
else: client_result = stats['client_alpn_protocol']
msg = "failed trying %s (s) and %s (c).\n" \ self.assertEqual(client_result, expected,
"was expecting %s, but got %%s from the %%s" \ msg % (client_result, "client"))
% (str(server_protocols), str(client_protocols), server_result = stats['server_alpn_protocols'][-1] \
str(expected)) if len(stats['server_alpn_protocols']) else 'nothing'
client_result = stats['client_alpn_protocol'] self.assertEqual(server_result, expected,
self.assertEqual(client_result, expected, msg % (server_result, "server"))
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): def test_selected_npn_protocol(self):
# selected_npn_protocol() is None unless NPN is used # selected_npn_protocol() is None unless NPN is used
@ -4175,31 +4132,8 @@ class ThreadedTests(unittest.TestCase):
sni_name=hostname) sni_name=hostname)
self.assertIs(stats['client_npn_protocol'], None) self.assertIs(stats['client_npn_protocol'], None)
@unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test")
def test_npn_protocols(self): def test_npn_protocols(self):
server_protocols = ['http/1.1', 'spdy/2'] assert not ssl.HAS_NPN
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"))
def sni_contexts(self): def sni_contexts(self):
server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
@ -4369,8 +4303,7 @@ class ThreadedTests(unittest.TestCase):
self.assertGreater(session.time, 0) self.assertGreater(session.time, 0)
self.assertGreater(session.timeout, 0) self.assertGreater(session.timeout, 0)
self.assertTrue(session.has_ticket) 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']) self.assertFalse(stats['session_reused'])
sess_stat = server_context.session_stats() sess_stat = server_context.session_stats()
self.assertEqual(sess_stat['accept'], 1) 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 socketmodule.c
# Socket module helper for SSL support; you must comment out the other # Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable: # socket line above, and edit the OPENSSL variable:
#SSL=/usr/local/ssl # OPENSSL=/path/to/openssl/directory
#_ssl _ssl.c \ # _ssl _ssl.c \
# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \ # -I$(OPENSSL)/include -L$(OPENSSL)/lib \
# -L$(SSL)/lib -lssl -lcrypto # -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 # The crypt module is now disabled by default because it breaks builds
# on many systems (where -lcrypt is needed), e.g. Linux (I believe). # 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" # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL"
#endif #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 #define MUNCH_SIZE INT_MAX
#ifdef NID_sha3_224 #define PY_OPENSSL_HAS_SCRYPT 1
#define PY_OPENSSL_HAS_SHA3 1 #define PY_OPENSSL_HAS_SHA3 1
#endif
#if defined(EVP_MD_FLAG_XOF) && defined(NID_shake128)
#define PY_OPENSSL_HAS_SHAKE 1 #define PY_OPENSSL_HAS_SHAKE 1
#endif
#if defined(NID_blake2b512) && !defined(OPENSSL_NO_BLAKE2)
#define PY_OPENSSL_HAS_BLAKE2 1 #define PY_OPENSSL_HAS_BLAKE2 1
#endif
static PyModuleDef _hashlibmodule; static PyModuleDef _hashlibmodule;
@ -1252,8 +1213,7 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name,
return key_obj; return key_obj;
} }
#if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER) #ifdef PY_OPENSSL_HAS_SCRYPT
#define PY_SCRYPT 1
/* XXX: Parameters salt, n, r and p should be required keyword-only parameters. /* 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 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; return key_obj;
} }
#endif #endif /* PY_OPENSSL_HAS_SCRYPT */
/* Fast HMAC for hmac.digest() /* Fast HMAC for hmac.digest()
*/ */
@ -1844,12 +1804,6 @@ hashlib_md_meth_names(PyObject *module)
return 0; 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] /*[clinic input]
_hashlib.get_fips_mode -> int _hashlib.get_fips_mode -> int
@ -1887,7 +1841,6 @@ _hashlib_get_fips_mode_impl(PyObject *module)
return result; return result;
#endif #endif
} }
#endif // !LIBRESSL_VERSION_NUMBER
static int static int
@ -2067,17 +2020,6 @@ hashlib_free(void *m)
} }
/* Py_mod_exec functions */ /* 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 static int
hashlib_init_evptype(PyObject *module) hashlib_init_evptype(PyObject *module)
{ {
@ -2200,8 +2142,6 @@ hashlib_exception(PyObject *module)
static PyModuleDef_Slot hashlib_slots[] = { 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_evptype},
{Py_mod_exec, hashlib_init_evpxoftype}, {Py_mod_exec, hashlib_init_evpxoftype},
{Py_mod_exec, hashlib_init_hmactype}, {Py_mod_exec, hashlib_init_hmactype},

View file

@ -29,9 +29,9 @@
#define _PySSL_FIX_ERRNO #define _PySSL_FIX_ERRNO
#define PySSL_BEGIN_ALLOW_THREADS_S(save) \ #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) \ #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 { \ #define PySSL_BEGIN_ALLOW_THREADS { \
PyThreadState *_save = NULL; \ PyThreadState *_save = NULL; \
PySSL_BEGIN_ALLOW_THREADS_S(_save); PySSL_BEGIN_ALLOW_THREADS_S(_save);
@ -62,16 +62,6 @@ static PySocketModule_APIObject PySocketModule;
#include "openssl/bio.h" #include "openssl/bio.h"
#include "openssl/dh.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 #ifndef OPENSSL_THREADS
# error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL" # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL"
#endif #endif
@ -142,15 +132,7 @@ static void _PySSLFixErrno(void) {
#include "_ssl_data.h" #include "_ssl_data.h"
#endif #endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL API 1.1.0+ does not include version methods */
# 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.
*/
#ifndef OPENSSL_NO_TLS1_METHOD #ifndef OPENSSL_NO_TLS1_METHOD
extern const SSL_METHOD *TLSv1_method(void); extern const SSL_METHOD *TLSv1_method(void);
#endif #endif
@ -161,129 +143,12 @@ extern const SSL_METHOD *TLSv1_1_method(void);
extern const SSL_METHOD *TLSv1_2_method(void); extern const SSL_METHOD *TLSv1_2_method(void);
#endif #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 */ #ifndef INVALID_SOCKET /* MS defines this */
#define INVALID_SOCKET (-1) #define INVALID_SOCKET (-1)
#endif #endif
/* OpenSSL 1.0.2 and LibreSSL needs extra code for locking */ /* OpenSSL 1.1 does not have SSL 2.0 */
#ifndef OPENSSL_VERSION_1_1
#define HAVE_OPENSSL_CRYPTO_LOCK
#endif
#if defined(OPENSSL_VERSION_1_1) && !defined(OPENSSL_NO_SSL2)
#define OPENSSL_NO_SSL2 #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 */ /* Default cipher suites */
#ifndef PY_SSL_DEFAULT_CIPHERS #ifndef PY_SSL_DEFAULT_CIPHERS
@ -395,24 +260,10 @@ enum py_proto_version {
#endif #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 */ /* SSL socket object */
#define X509_NAME_MAXLEN 256 #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 /* In case of 'tls-unique' it will be 12 bytes for TLS, 36 bytes for
* older SSL, but let's be safe */ * older SSL, but let's be safe */
@ -422,17 +273,9 @@ static unsigned int _ssl_locks_count = 0;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
SSL_CTX *ctx; SSL_CTX *ctx;
#if HAVE_NPN
unsigned char *npn_protocols;
int npn_protocols_len;
#endif
#if HAVE_ALPN
unsigned char *alpn_protocols; unsigned char *alpn_protocols;
unsigned int alpn_protocols_len; unsigned int alpn_protocols_len;
#endif
#ifndef OPENSSL_NO_TLSEXT
PyObject *set_sni_cb; PyObject *set_sni_cb;
#endif
int check_hostname; int check_hostname;
/* OpenSSL has no API to get hostflags from X509_VERIFY_PARAM* struct. /* 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. * We have to maintain our own copy. OpenSSL's hostflags default to 0.
@ -443,10 +286,8 @@ typedef struct {
int post_handshake_auth; int post_handshake_auth;
#endif #endif
PyObject *msg_cb; PyObject *msg_cb;
#ifdef HAVE_OPENSSL_KEYLOG
PyObject *keylog_filename; PyObject *keylog_filename;
BIO *keylog_bio; BIO *keylog_bio;
#endif
} PySSLContext; } PySSLContext;
typedef struct { typedef struct {
@ -652,23 +493,18 @@ fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno,
} }
switch (verify_code) { switch (verify_code) {
#ifdef X509_V_ERR_HOSTNAME_MISMATCH
/* OpenSSL >= 1.0.2, LibreSSL >= 2.5.3 */
case X509_V_ERR_HOSTNAME_MISMATCH: case X509_V_ERR_HOSTNAME_MISMATCH:
verify_obj = PyUnicode_FromFormat( verify_obj = PyUnicode_FromFormat(
"Hostname mismatch, certificate is not valid for '%S'.", "Hostname mismatch, certificate is not valid for '%S'.",
sslsock->server_hostname sslsock->server_hostname
); );
break; break;
#endif
#ifdef X509_V_ERR_IP_ADDRESS_MISMATCH
case X509_V_ERR_IP_ADDRESS_MISMATCH: case X509_V_ERR_IP_ADDRESS_MISMATCH:
verify_obj = PyUnicode_FromFormat( verify_obj = PyUnicode_FromFormat(
"IP address mismatch, certificate is not valid for '%S'.", "IP address mismatch, certificate is not valid for '%S'.",
sslsock->server_hostname sslsock->server_hostname
); );
break; break;
#endif
default: default:
verify_str = X509_verify_cert_error_string(verify_code); verify_str = X509_verify_cert_error_string(verify_code);
if (verify_str != NULL) { if (verify_str != NULL) {
@ -1995,7 +1831,6 @@ cipher_to_tuple(const SSL_CIPHER *cipher)
return NULL; return NULL;
} }
#if OPENSSL_VERSION_NUMBER >= 0x10002000UL
static PyObject * static PyObject *
cipher_to_dict(const SSL_CIPHER *cipher) cipher_to_dict(const SSL_CIPHER *cipher)
{ {
@ -2004,10 +1839,8 @@ cipher_to_dict(const SSL_CIPHER *cipher)
unsigned long cipher_id; unsigned long cipher_id;
int alg_bits, strength_bits, len; int alg_bits, strength_bits, len;
char buf[512] = {0}; char buf[512] = {0};
#if OPENSSL_VERSION_1_1
int aead, nid; int aead, nid;
const char *skcipher = NULL, *digest = NULL, *kx = NULL, *auth = NULL; const char *skcipher = NULL, *digest = NULL, *kx = NULL, *auth = NULL;
#endif
/* can be NULL */ /* can be NULL */
cipher_name = SSL_CIPHER_get_name(cipher); cipher_name = SSL_CIPHER_get_name(cipher);
@ -2020,7 +1853,6 @@ cipher_to_dict(const SSL_CIPHER *cipher)
buf[len-1] = '\0'; buf[len-1] = '\0';
strength_bits = SSL_CIPHER_get_bits(cipher, &alg_bits); strength_bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
#if OPENSSL_VERSION_1_1
aead = SSL_CIPHER_is_aead(cipher); aead = SSL_CIPHER_is_aead(cipher);
nid = SSL_CIPHER_get_cipher_nid(cipher); nid = SSL_CIPHER_get_cipher_nid(cipher);
skcipher = nid != NID_undef ? OBJ_nid2ln(nid) : NULL; 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; kx = nid != NID_undef ? OBJ_nid2ln(nid) : NULL;
nid = SSL_CIPHER_get_auth_nid(cipher); nid = SSL_CIPHER_get_auth_nid(cipher);
auth = nid != NID_undef ? OBJ_nid2ln(nid) : NULL; auth = nid != NID_undef ? OBJ_nid2ln(nid) : NULL;
#endif
return Py_BuildValue( return Py_BuildValue(
"{sksssssssisi" "{sksssssssisi"
#if OPENSSL_VERSION_1_1
"sOssssssss" "sOssssssss"
#endif
"}", "}",
"id", cipher_id, "id", cipher_id,
"name", cipher_name, "name", cipher_name,
@ -2044,16 +1873,13 @@ cipher_to_dict(const SSL_CIPHER *cipher)
"description", buf, "description", buf,
"strength_bits", strength_bits, "strength_bits", strength_bits,
"alg_bits", alg_bits "alg_bits", alg_bits
#if OPENSSL_VERSION_1_1
,"aead", aead ? Py_True : Py_False, ,"aead", aead ? Py_True : Py_False,
"symmetric", skcipher, "symmetric", skcipher,
"digest", digest, "digest", digest,
"kea", kx, "kea", kx,
"auth", auth "auth", auth
#endif
); );
} }
#endif
/*[clinic input] /*[clinic input]
_ssl._SSLSocket.shared_ciphers _ssl._SSLSocket.shared_ciphers
@ -2124,28 +1950,6 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self)
return PyUnicode_FromString(version); 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] /*[clinic input]
_ssl._SSLSocket.selected_alpn_protocol _ssl._SSLSocket.selected_alpn_protocol
[clinic start generated code]*/ [clinic start generated code]*/
@ -2163,7 +1967,6 @@ _ssl__SSLSocket_selected_alpn_protocol_impl(PySSLSocket *self)
Py_RETURN_NONE; Py_RETURN_NONE;
return PyUnicode_FromStringAndSize((char *)out, outlen); return PyUnicode_FromStringAndSize((char *)out, outlen);
} }
#endif
/*[clinic input] /*[clinic input]
_ssl._SSLSocket.compression _ssl._SSLSocket.compression
@ -2200,11 +2003,6 @@ static int PySSL_set_context(PySSLSocket *self, PyObject *value,
void *closure) { void *closure) {
if (PyObject_TypeCheck(value, PySSLContext_Type)) { 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_INCREF(value);
Py_SETREF(self->ctx, (PySSLContext *)value); Py_SETREF(self->ctx, (PySSLContext *)value);
SSL_set_SSL_CTX(self->ssl, self->ctx->ctx); 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->ssl,
self->ctx->msg_cb ? _PySSL_msg_callback : NULL self->ctx->msg_cb ? _PySSL_msg_callback : NULL
); );
#endif
} else { } else {
PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext"); PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext");
return -1; return -1;
@ -2840,8 +2637,6 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self)
#endif #endif
} }
#ifdef OPENSSL_VERSION_1_1
static SSL_SESSION* static SSL_SESSION*
_ssl_session_dup(SSL_SESSION *session) { _ssl_session_dup(SSL_SESSION *session) {
SSL_SESSION *newsession = NULL; SSL_SESSION *newsession = NULL;
@ -2882,7 +2677,6 @@ _ssl_session_dup(SSL_SESSION *session) {
} }
return NULL; return NULL;
} }
#endif
static PyObject * static PyObject *
PySSL_get_session(PySSLSocket *self, void *closure) { PySSL_get_session(PySSLSocket *self, void *closure) {
@ -2891,7 +2685,6 @@ PySSL_get_session(PySSLSocket *self, void *closure) {
PySSLSession *pysess; PySSLSession *pysess;
SSL_SESSION *session; SSL_SESSION *session;
#ifdef OPENSSL_VERSION_1_1
/* duplicate session as workaround for session bug in OpenSSL 1.1.0, /* duplicate session as workaround for session bug in OpenSSL 1.1.0,
* https://github.com/openssl/openssl/issues/1550 */ * https://github.com/openssl/openssl/issues/1550 */
session = SSL_get0_session(self->ssl); /* borrowed reference */ 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) { if ((session = _ssl_session_dup(session)) == NULL) {
return NULL; return NULL;
} }
#else
session = SSL_get1_session(self->ssl); session = SSL_get1_session(self->ssl);
if (session == NULL) { if (session == NULL) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
#endif
pysess = PyObject_GC_New(PySSLSession, PySSLSession_Type); pysess = PyObject_GC_New(PySSLSession, PySSLSession_Type);
if (pysess == NULL) { if (pysess == NULL) {
SSL_SESSION_free(session); SSL_SESSION_free(session);
@ -2925,9 +2716,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
void *closure) void *closure)
{ {
PySSLSession *pysess; PySSLSession *pysess;
#ifdef OPENSSL_VERSION_1_1
SSL_SESSION *session; SSL_SESSION *session;
#endif
int result; int result;
if (!PySSLSession_Check(value)) { if (!PySSLSession_Check(value)) {
@ -2951,7 +2740,6 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
"Cannot set session after handshake."); "Cannot set session after handshake.");
return -1; return -1;
} }
#ifdef OPENSSL_VERSION_1_1
/* duplicate session */ /* duplicate session */
if ((session = _ssl_session_dup(pysess->session)) == NULL) { if ((session = _ssl_session_dup(pysess->session)) == NULL) {
return -1; return -1;
@ -2959,9 +2747,6 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
result = SSL_set_session(self->ssl, session); result = SSL_set_session(self->ssl, session);
/* free duplicate, SSL_set_session() bumps ref count */ /* free duplicate, SSL_set_session() bumps ref count */
SSL_SESSION_free(session); SSL_SESSION_free(session);
#else
result = SSL_set_session(self->ssl, pysess->session);
#endif
if (result == 0) { if (result == 0) {
_setSSLError(NULL, 0, __FILE__, __LINE__); _setSSLError(NULL, 0, __FILE__, __LINE__);
return -1; return -1;
@ -3012,7 +2797,6 @@ static PyMethodDef PySSLMethods[] = {
_SSL__SSLSOCKET_CIPHER_METHODDEF _SSL__SSLSOCKET_CIPHER_METHODDEF
_SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF _SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF
_SSL__SSLSOCKET_VERSION_METHODDEF _SSL__SSLSOCKET_VERSION_METHODDEF
_SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF
_SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF
_SSL__SSLSOCKET_COMPRESSION_METHODDEF _SSL__SSLSOCKET_COMPRESSION_METHODDEF
_SSL__SSLSOCKET_SHUTDOWN_METHODDEF _SSL__SSLSOCKET_SHUTDOWN_METHODDEF
@ -3089,9 +2873,6 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
SSL_CTX *ctx = NULL; SSL_CTX *ctx = NULL;
X509_VERIFY_PARAM *params; X509_VERIFY_PARAM *params;
int result; int result;
#if defined(SSL_MODE_RELEASE_BUFFERS)
unsigned long libver;
#endif
PySSL_BEGIN_ALLOW_THREADS PySSL_BEGIN_ALLOW_THREADS
switch(proto_version) { switch(proto_version) {
@ -3156,19 +2937,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS;
self->protocol = proto_version; self->protocol = proto_version;
self->msg_cb = NULL; self->msg_cb = NULL;
#ifdef HAVE_OPENSSL_KEYLOG
self->keylog_filename = NULL; self->keylog_filename = NULL;
self->keylog_bio = NULL; self->keylog_bio = NULL;
#endif
#if HAVE_NPN
self->npn_protocols = NULL;
#endif
#if HAVE_ALPN
self->alpn_protocols = NULL; self->alpn_protocols = NULL;
#endif
#ifndef OPENSSL_NO_TLSEXT
self->set_sni_cb = NULL; self->set_sni_cb = NULL;
#endif
/* Don't check host name by default */ /* Don't check host name by default */
if (proto_version == PY_SSL_VERSION_TLS_CLIENT) { if (proto_version == PY_SSL_VERSION_TLS_CLIENT) {
self->check_hostname = 1; self->check_hostname = 1;
@ -3230,37 +3002,9 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
return NULL; return NULL;
} }
#if defined(SSL_MODE_RELEASE_BUFFERS)
/* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory /* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory
usage for no cost at all. However, don't do this for OpenSSL versions usage for no cost at all. */
between 1.0.1 and 1.0.1h or 1.0.0 and 1.0.0m, which are affected by CVE SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS);
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
#define SID_CTX "Python" #define SID_CTX "Python"
SSL_CTX_set_session_id_context(self->ctx, (const unsigned char *) SID_CTX, 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 #undef SID_CTX
params = SSL_CTX_get0_param(self->ctx); params = SSL_CTX_get0_param(self->ctx);
#ifdef X509_V_FLAG_TRUSTED_FIRST
/* Improve trust chain building when cross-signed intermediate /* Improve trust chain building when cross-signed intermediate
certificates are present. See https://bugs.python.org/issue23476. */ certificates are present. See https://bugs.python.org/issue23476. */
X509_VERIFY_PARAM_set_flags(params, X509_V_FLAG_TRUSTED_FIRST); X509_VERIFY_PARAM_set_flags(params, X509_V_FLAG_TRUSTED_FIRST);
#endif
X509_VERIFY_PARAM_set_hostflags(params, self->hostflags); X509_VERIFY_PARAM_set_hostflags(params, self->hostflags);
#ifdef TLS1_3_VERSION #ifdef TLS1_3_VERSION
@ -3286,9 +3028,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
static int static int
context_traverse(PySSLContext *self, visitproc visit, void *arg) context_traverse(PySSLContext *self, visitproc visit, void *arg)
{ {
#ifndef OPENSSL_NO_TLSEXT
Py_VISIT(self->set_sni_cb); Py_VISIT(self->set_sni_cb);
#endif
Py_VISIT(self->msg_cb); Py_VISIT(self->msg_cb);
return 0; return 0;
} }
@ -3296,11 +3036,8 @@ context_traverse(PySSLContext *self, visitproc visit, void *arg)
static int static int
context_clear(PySSLContext *self) context_clear(PySSLContext *self)
{ {
#ifndef OPENSSL_NO_TLSEXT
Py_CLEAR(self->set_sni_cb); Py_CLEAR(self->set_sni_cb);
#endif
Py_CLEAR(self->msg_cb); Py_CLEAR(self->msg_cb);
#ifdef HAVE_OPENSSL_KEYLOG
Py_CLEAR(self->keylog_filename); Py_CLEAR(self->keylog_filename);
if (self->keylog_bio != NULL) { if (self->keylog_bio != NULL) {
PySSL_BEGIN_ALLOW_THREADS PySSL_BEGIN_ALLOW_THREADS
@ -3308,7 +3045,6 @@ context_clear(PySSLContext *self)
PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS
self->keylog_bio = NULL; self->keylog_bio = NULL;
} }
#endif
return 0; return 0;
} }
@ -3320,12 +3056,7 @@ context_dealloc(PySSLContext *self)
PyObject_GC_UnTrack(self); PyObject_GC_UnTrack(self);
context_clear(self); context_clear(self);
SSL_CTX_free(self->ctx); SSL_CTX_free(self->ctx);
#if HAVE_NPN PyMem_FREE(self->alpn_protocols);
PyMem_Free(self->npn_protocols);
#endif
#if HAVE_ALPN
PyMem_Free(self->alpn_protocols);
#endif
Py_TYPE(self)->tp_free(self); Py_TYPE(self)->tp_free(self);
Py_DECREF(tp); Py_DECREF(tp);
} }
@ -3353,7 +3084,6 @@ _ssl__SSLContext_set_ciphers_impl(PySSLContext *self, const char *cipherlist)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
#if OPENSSL_VERSION_NUMBER >= 0x10002000UL
/*[clinic input] /*[clinic input]
_ssl._SSLContext.get_ciphers _ssl._SSLContext.get_ciphers
[clinic start generated code]*/ [clinic start generated code]*/
@ -3396,10 +3126,8 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self)
return result; return result;
} }
#endif
#if HAVE_NPN || HAVE_ALPN
static int static int
do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen,
const unsigned char *server_protocols, unsigned int server_protocols_len, 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; 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 static int
_selectALPN_cb(SSL *s, _selectALPN_cb(SSL *s,
const unsigned char **out, unsigned char *outlen, const unsigned char **out, unsigned char *outlen,
@ -3505,7 +3163,6 @@ _selectALPN_cb(SSL *s,
ctx->alpn_protocols, ctx->alpn_protocols_len, ctx->alpn_protocols, ctx->alpn_protocols_len,
client_protocols, client_protocols_len); client_protocols, client_protocols_len);
} }
#endif
/*[clinic input] /*[clinic input]
_ssl._SSLContext._set_alpn_protocols _ssl._SSLContext._set_alpn_protocols
@ -3518,7 +3175,6 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self,
Py_buffer *protos) Py_buffer *protos)
/*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/ /*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/
{ {
#if HAVE_ALPN
if ((size_t)protos->len > UINT_MAX) { if ((size_t)protos->len > UINT_MAX) {
PyErr_Format(PyExc_OverflowError, PyErr_Format(PyExc_OverflowError,
"protocols longer than %u bytes", UINT_MAX); "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); SSL_CTX_set_alpn_select_cb(self->ctx, _selectALPN_cb, self);
Py_RETURN_NONE; Py_RETURN_NONE;
#else
PyErr_SetString(PyExc_NotImplementedError,
"The ALPN extension requires OpenSSL 1.0.2 or later.");
return NULL;
#endif
} }
static PyObject * static PyObject *
@ -3617,9 +3268,6 @@ set_verify_flags(PySSLContext *self, PyObject *arg, void *c)
} }
/* Getter and setter for protocol version */ /* Getter and setter for protocol version */
#if defined(SSL_CTRL_GET_MAX_PROTO_VERSION)
static int static int
set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) 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); 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 * static PyObject *
get_num_tickets(PySSLContext *self, void *c) 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, PyDoc_STRVAR(PySSLContext_num_tickets_doc,
"Control the number of TLSv1.3 session tickets"); "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 * static PyObject *
get_security_level(PySSLContext *self, void *c) get_security_level(PySSLContext *self, void *c)
{ {
return PyLong_FromLong(SSL_CTX_get_security_level(self->ctx)); return PyLong_FromLong(SSL_CTX_get_security_level(self->ctx));
} }
PyDoc_STRVAR(PySSLContext_security_level_doc, "The current security level"); PyDoc_STRVAR(PySSLContext_security_level_doc, "The current security level");
#endif /* OpenSSL 1.1.0 */
static PyObject * static PyObject *
get_options(PySSLContext *self, void *c) get_options(PySSLContext *self, void *c)
@ -3774,13 +3419,7 @@ set_options(PySSLContext *self, PyObject *arg, void *c)
clear = opts & ~new_opts; clear = opts & ~new_opts;
set = ~opts & new_opts; set = ~opts & new_opts;
if (clear) { if (clear) {
#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS
SSL_CTX_clear_options(self->ctx, clear); 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) if (set)
SSL_CTX_set_options(self->ctx, set); SSL_CTX_set_options(self->ctx, set);
@ -4468,7 +4107,6 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
#ifndef OPENSSL_NO_ECDH
/*[clinic input] /*[clinic input]
_ssl._SSLContext.set_ecdh_curve _ssl._SSLContext.set_ecdh_curve
name: object name: object
@ -4503,9 +4141,7 @@ _ssl__SSLContext_set_ecdh_curve(PySSLContext *self, PyObject *name)
EC_KEY_free(key); EC_KEY_free(key);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
#endif
#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT)
static int static int
_servername_callback(SSL *s, int *al, void *args) _servername_callback(SSL *s, int *al, void *args)
{ {
@ -4609,7 +4245,6 @@ error:
PyGILState_Release(gstate); PyGILState_Release(gstate);
return ret; return ret;
} }
#endif
static PyObject * static PyObject *
get_sni_callback(PySSLContext *self, void *c) 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"); "sni_callback cannot be set on TLS_CLIENT context");
return -1; return -1;
} }
#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT)
Py_CLEAR(self->set_sni_cb); Py_CLEAR(self->set_sni_cb);
if (arg == Py_None) { if (arg == Py_None) {
SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); 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); SSL_CTX_set_tlsext_servername_arg(self->ctx, self);
} }
return 0; 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, PyDoc_STRVAR(PySSLContext_sni_callback_doc,
@ -4779,21 +4406,17 @@ static PyGetSetDef context_getsetlist[] = {
(setter) set_check_hostname, NULL}, (setter) set_check_hostname, NULL},
{"_host_flags", (getter) get_host_flags, {"_host_flags", (getter) get_host_flags,
(setter) set_host_flags, NULL}, (setter) set_host_flags, NULL},
#if SSL_CTRL_GET_MAX_PROTO_VERSION
{"minimum_version", (getter) get_minimum_version, {"minimum_version", (getter) get_minimum_version,
(setter) set_minimum_version, NULL}, (setter) set_minimum_version, NULL},
{"maximum_version", (getter) get_maximum_version, {"maximum_version", (getter) get_maximum_version,
(setter) set_maximum_version, NULL}, (setter) set_maximum_version, NULL},
#endif
#ifdef HAVE_OPENSSL_KEYLOG
{"keylog_filename", (getter) _PySSLContext_get_keylog_filename, {"keylog_filename", (getter) _PySSLContext_get_keylog_filename,
(setter) _PySSLContext_set_keylog_filename, NULL}, (setter) _PySSLContext_set_keylog_filename, NULL},
#endif
{"_msg_callback", (getter) _PySSLContext_get_msg_callback, {"_msg_callback", (getter) _PySSLContext_get_msg_callback,
(setter) _PySSLContext_set_msg_callback, NULL}, (setter) _PySSLContext_set_msg_callback, NULL},
{"sni_callback", (getter) get_sni_callback, {"sni_callback", (getter) get_sni_callback,
(setter) set_sni_callback, PySSLContext_sni_callback_doc}, (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, {"num_tickets", (getter) get_num_tickets,
(setter) set_num_tickets, PySSLContext_num_tickets_doc}, (setter) set_num_tickets, PySSLContext_num_tickets_doc},
#endif #endif
@ -4812,10 +4435,8 @@ static PyGetSetDef context_getsetlist[] = {
(setter) set_verify_flags, NULL}, (setter) set_verify_flags, NULL},
{"verify_mode", (getter) get_verify_mode, {"verify_mode", (getter) get_verify_mode,
(setter) set_verify_mode, NULL}, (setter) set_verify_mode, NULL},
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
{"security_level", (getter) get_security_level, {"security_level", (getter) get_security_level,
NULL, PySSLContext_security_level_doc}, NULL, PySSLContext_security_level_doc},
#endif
{NULL}, /* sentinel */ {NULL}, /* sentinel */
}; };
@ -4824,7 +4445,6 @@ static struct PyMethodDef context_methods[] = {
_SSL__SSLCONTEXT__WRAP_BIO_METHODDEF _SSL__SSLCONTEXT__WRAP_BIO_METHODDEF
_SSL__SSLCONTEXT_SET_CIPHERS_METHODDEF _SSL__SSLCONTEXT_SET_CIPHERS_METHODDEF
_SSL__SSLCONTEXT__SET_ALPN_PROTOCOLS_METHODDEF _SSL__SSLCONTEXT__SET_ALPN_PROTOCOLS_METHODDEF
_SSL__SSLCONTEXT__SET_NPN_PROTOCOLS_METHODDEF
_SSL__SSLCONTEXT_LOAD_CERT_CHAIN_METHODDEF _SSL__SSLCONTEXT_LOAD_CERT_CHAIN_METHODDEF
_SSL__SSLCONTEXT_LOAD_DH_PARAMS_METHODDEF _SSL__SSLCONTEXT_LOAD_DH_PARAMS_METHODDEF
_SSL__SSLCONTEXT_LOAD_VERIFY_LOCATIONS_METHODDEF _SSL__SSLCONTEXT_LOAD_VERIFY_LOCATIONS_METHODDEF
@ -5281,11 +4901,7 @@ PySSL_RAND(int len, int pseudo)
if (bytes == NULL) if (bytes == NULL)
return NULL; return NULL;
if (pseudo) { if (pseudo) {
#ifdef PY_OPENSSL_1_1_API
ok = RAND_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len); 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) if (ok == 0 || ok == 1)
return Py_BuildValue("NO", bytes, ok == 1 ? Py_True : Py_False); 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 static int
sslmodule_init_types(PyObject *module) sslmodule_init_types(PyObject *module)
{ {
@ -6205,10 +5735,8 @@ sslmodule_init_constants(PyObject *m)
X509_V_FLAG_X509_STRICT); X509_V_FLAG_X509_STRICT);
PyModule_AddIntConstant(m, "VERIFY_ALLOW_PROXY_CERTS", PyModule_AddIntConstant(m, "VERIFY_ALLOW_PROXY_CERTS",
X509_V_FLAG_ALLOW_PROXY_CERTS); X509_V_FLAG_ALLOW_PROXY_CERTS);
#ifdef X509_V_FLAG_TRUSTED_FIRST
PyModule_AddIntConstant(m, "VERIFY_X509_TRUSTED_FIRST", PyModule_AddIntConstant(m, "VERIFY_X509_TRUSTED_FIRST",
X509_V_FLAG_TRUSTED_FIRST); X509_V_FLAG_TRUSTED_FIRST);
#endif
/* Alert Descriptions from ssl.h */ /* Alert Descriptions from ssl.h */
/* note RESERVED constants no longer intended for use have been removed */ /* 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); \ PyModule_AddObject((m), (key), bool_obj); \
} while (0) } while (0)
#if HAVE_SNI
addbool(m, "HAS_SNI", 1); addbool(m, "HAS_SNI", 1);
#else
addbool(m, "HAS_SNI", 0);
#endif
addbool(m, "HAS_TLS_UNIQUE", 1); addbool(m, "HAS_TLS_UNIQUE", 1);
#ifndef OPENSSL_NO_ECDH
addbool(m, "HAS_ECDH", 1); 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); addbool(m, "HAS_NPN", 0);
#endif
#if HAVE_ALPN
addbool(m, "HAS_ALPN", 1); addbool(m, "HAS_ALPN", 1);
#else
addbool(m, "HAS_ALPN", 0);
#endif
#if defined(SSL2_VERSION) && !defined(OPENSSL_NO_SSL2) #if defined(SSL2_VERSION) && !defined(OPENSSL_NO_SSL2)
addbool(m, "HAS_SSLv2", 1); addbool(m, "HAS_SSLv2", 1);
@ -6430,29 +5938,6 @@ sslmodule_init_constants(PyObject *m)
return 0; 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, PyDoc_STRVAR(module_doc,
"Implementation module for SSL socket operations. See the socket module\n\ "Implementation module for SSL socket operations. See the socket module\n\
for documentation."); for documentation.");
@ -6491,8 +5976,6 @@ PyInit__ssl(void)
return NULL; return NULL;
if (sslmodule_init_versioninfo(m) != 0) if (sslmodule_init_versioninfo(m) != 0)
return NULL; return NULL;
if (sslmodule_legacy(m) != 0)
return NULL;
return m; return m;
} }

View file

@ -114,8 +114,6 @@ _PySSLContext_set_msg_callback(PySSLContext *self, PyObject *arg, void *c) {
return 0; return 0;
} }
#ifdef HAVE_OPENSSL_KEYLOG
static void static void
_PySSL_keylog_callback(const SSL *ssl, const char *line) _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); SSL_CTX_set_keylog_callback(self->ctx, _PySSL_keylog_callback);
return 0; return 0;
} }
#endif

View file

@ -950,7 +950,7 @@ exit:
return return_value; 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__, PyDoc_STRVAR(_hashlib_scrypt__doc__,
"scrypt($module, /, password, *, salt=None, n=None, r=None, p=None,\n" "scrypt($module, /, password, *, salt=None, n=None, r=None, p=None,\n"
@ -1068,7 +1068,7 @@ exit:
return return_value; 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__, PyDoc_STRVAR(_hashlib_hmac_singleshot__doc__,
"hmac_digest($module, /, key, msg, digest)\n" "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); return _hashlib_HMAC_hexdigest_impl(self);
} }
#if !defined(LIBRESSL_VERSION_NUMBER)
PyDoc_STRVAR(_hashlib_get_fips_mode__doc__, PyDoc_STRVAR(_hashlib_get_fips_mode__doc__,
"get_fips_mode($module, /)\n" "get_fips_mode($module, /)\n"
"--\n" "--\n"
@ -1312,8 +1310,6 @@ exit:
return return_value; return return_value;
} }
#endif /* !defined(LIBRESSL_VERSION_NUMBER) */
PyDoc_STRVAR(_hashlib_compare_digest__doc__, PyDoc_STRVAR(_hashlib_compare_digest__doc__,
"compare_digest($module, a, b, /)\n" "compare_digest($module, a, b, /)\n"
"--\n" "--\n"
@ -1389,8 +1385,4 @@ exit:
#ifndef _HASHLIB_SCRYPT_METHODDEF #ifndef _HASHLIB_SCRYPT_METHODDEF
#define _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF
#endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
/*[clinic end generated code: output=162369cb9d43f1cc input=a9049054013a1b77]*/
#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]*/

View file

@ -139,29 +139,6 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored))
return _ssl__SSLSocket_version_impl(self); 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__, PyDoc_STRVAR(_ssl__SSLSocket_selected_alpn_protocol__doc__,
"selected_alpn_protocol($self, /)\n" "selected_alpn_protocol($self, /)\n"
"--\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); return _ssl__SSLSocket_selected_alpn_protocol_impl(self);
} }
#endif /* (HAVE_ALPN) */
PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__, PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__,
"compression($self, /)\n" "compression($self, /)\n"
"--\n" "--\n"
@ -452,8 +427,6 @@ exit:
return return_value; return return_value;
} }
#if (OPENSSL_VERSION_NUMBER >= 0x10002000UL)
PyDoc_STRVAR(_ssl__SSLContext_get_ciphers__doc__, PyDoc_STRVAR(_ssl__SSLContext_get_ciphers__doc__,
"get_ciphers($self, /)\n" "get_ciphers($self, /)\n"
"--\n" "--\n"
@ -471,44 +444,6 @@ _ssl__SSLContext_get_ciphers(PySSLContext *self, PyObject *Py_UNUSED(ignored))
return _ssl__SSLContext_get_ciphers_impl(self); 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__, PyDoc_STRVAR(_ssl__SSLContext__set_alpn_protocols__doc__,
"_set_alpn_protocols($self, protos, /)\n" "_set_alpn_protocols($self, protos, /)\n"
"--\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); return _ssl__SSLContext_set_default_verify_paths_impl(self);
} }
#if !defined(OPENSSL_NO_ECDH)
PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__, PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__,
"set_ecdh_curve($self, name, /)\n" "set_ecdh_curve($self, name, /)\n"
"--\n" "--\n"
@ -839,8 +772,6 @@ PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__,
#define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF \ #define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF \
{"set_ecdh_curve", (PyCFunction)_ssl__SSLContext_set_ecdh_curve, METH_O, _ssl__SSLContext_set_ecdh_curve__doc__}, {"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__, PyDoc_STRVAR(_ssl__SSLContext_cert_store_stats__doc__,
"cert_store_stats($self, /)\n" "cert_store_stats($self, /)\n"
"--\n" "--\n"
@ -1420,22 +1351,6 @@ exit:
#endif /* defined(_MSC_VER) */ #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 #ifndef _SSL_RAND_EGD_METHODDEF
#define _SSL_RAND_EGD_METHODDEF #define _SSL_RAND_EGD_METHODDEF
#endif /* !defined(_SSL_RAND_EGD_METHODDEF) */ #endif /* !defined(_SSL_RAND_EGD_METHODDEF) */
@ -1447,4 +1362,4 @@ exit:
#ifndef _SSL_ENUM_CRLS_METHODDEF #ifndef _SSL_ENUM_CRLS_METHODDEF
#define _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF
#endif /* !defined(_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 @@ import tarfile
log = logging.getLogger("multissl") log = logging.getLogger("multissl")
OPENSSL_OLD_VERSIONS = [ OPENSSL_OLD_VERSIONS = [
"1.0.2u",
"1.1.0l",
] ]
OPENSSL_RECENT_VERSIONS = [ OPENSSL_RECENT_VERSIONS = [
"1.1.1k", "1.1.1k",
# "3.0.0-alpha14" "3.0.0-alpha14"
] ]
LIBRESSL_OLD_VERSIONS = [ LIBRESSL_OLD_VERSIONS = [
"2.9.2",
] ]
LIBRESSL_RECENT_VERSIONS = [ LIBRESSL_RECENT_VERSIONS = [
"3.2.4",
] ]
# store files in ../multissl # 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 # Check for usable OpenSSL
AX_CHECK_OPENSSL([have_openssl=yes],[have_openssl=no]) 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 # rpath to libssl and libcrypto
AC_MSG_CHECKING(for --with-openssl-rpath) AC_MSG_CHECKING(for --with-openssl-rpath)
AC_ARG_WITH(openssl-rpath, AC_ARG_WITH(openssl-rpath,

View file

@ -1356,9 +1356,6 @@
/* Define to 1 if you have the `writev' function. */ /* Define to 1 if you have the `writev' function. */
#undef HAVE_WRITEV #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 */ /* Define if the zlib library has inflateCopy */
#undef HAVE_ZLIB_COPY #undef HAVE_ZLIB_COPY

View file

@ -551,10 +551,7 @@ class PyBuildExt(build_ext):
for l in (self.missing, self.failed, self.failed_on_import)): for l in (self.missing, self.failed, self.failed_on_import)):
print() print()
print("Could not build the ssl module!") print("Could not build the ssl module!")
print("Python requires an OpenSSL 1.0.2 or 1.1 compatible " print("Python requires a OpenSSL 1.1.1 or newer")
"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")
if sysconfig.get_config_var("OPENSSL_LDFLAGS"): if sysconfig.get_config_var("OPENSSL_LDFLAGS"):
print("Custom linker flags may require --with-openssl-rpath=auto") print("Custom linker flags may require --with-openssl-rpath=auto")
print() print()
@ -2431,13 +2428,13 @@ class PyBuildExt(build_ext):
self.missing.extend(['_ssl', '_hashlib']) self.missing.extend(['_ssl', '_hashlib'])
return None, None return None, None
# OpenSSL 1.0.2 uses Kerberos for KRB5 ciphers self.add(Extension(
krb5_h = find_file( '_ssl', ['_ssl.c'],
'krb5.h', self.inc_dirs, include_dirs=openssl_includes,
['/usr/kerberos/include'] 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': if openssl_rpath == 'auto':
runtime_library_dirs = openssl_libdirs[:] runtime_library_dirs = openssl_libdirs[:]
@ -2468,24 +2465,14 @@ class PyBuildExt(build_ext):
# don't link OpenSSL shared libraries. # don't link OpenSSL shared libraries.
openssl_extension_kwargs["libraries"] = [] openssl_extension_kwargs["libraries"] = []
if config_vars.get("HAVE_X509_VERIFY_PARAM_SET1_HOST"): self.add(
self.add( Extension(
Extension( '_ssl',
'_ssl', ['_ssl.c'],
['_ssl.c'], depends=['socketmodule.h', '_ssl/debughelpers.c'],
depends=[ **openssl_extension_kwargs
'socketmodule.h',
'_ssl/debughelpers.c',
'_ssl_data.h',
'_ssl_data_111.h',
'_ssl_data_300.h',
],
**openssl_extension_kwargs
)
) )
else: )
self.missing.append('_ssl')
self.add( self.add(
Extension( Extension(
'_hashlib', '_hashlib',