Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 28 additions & 24 deletions Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ def test_constants(self):
ssl.OP_NO_COMPRESSION
self.assertEqual(ssl.HAS_SNI, True)
self.assertEqual(ssl.HAS_ECDH, True)
self.assertEqual(ssl.HAS_TLSv1_2, True)
ssl.HAS_TLSv1_2
self.assertEqual(ssl.HAS_TLSv1_3, True)
ssl.OP_NO_SSLv2
ssl.OP_NO_SSLv3
Expand Down Expand Up @@ -586,11 +586,11 @@ def test_openssl_version(self):
# Some sanity checks follow
# >= 1.1.1
self.assertGreaterEqual(n, 0x10101000)
# < 4.0
self.assertLess(n, 0x40000000)
# < 5.0
self.assertLess(n, 0x50000000)
major, minor, fix, patch, status = t
self.assertGreaterEqual(major, 1)
self.assertLess(major, 4)
self.assertLess(major, 5)
self.assertGreaterEqual(minor, 0)
self.assertLess(minor, 256)
self.assertGreaterEqual(fix, 0)
Expand Down Expand Up @@ -656,12 +656,14 @@ def test_openssl111_deprecations(self):
ssl.OP_NO_TLSv1_2,
ssl.OP_NO_TLSv1_3
]
protocols = [
ssl.PROTOCOL_TLSv1,
ssl.PROTOCOL_TLSv1_1,
ssl.PROTOCOL_TLSv1_2,
ssl.PROTOCOL_TLS
]
protocols = []
if hasattr(ssl, 'PROTOCOL_TLSv1'):
protocols.append(ssl.PROTOCOL_TLSv1)
if hasattr(ssl, 'PROTOCOL_TLSv1_1'):
protocols.append(ssl.PROTOCOL_TLSv1_1)
if hasattr(ssl, 'PROTOCOL_TLSv1_2'):
protocols.append(ssl.PROTOCOL_TLSv1_2)
protocols.append(ssl.PROTOCOL_TLS)
versions = [
ssl.TLSVersion.SSLv3,
ssl.TLSVersion.TLSv1,
Expand Down Expand Up @@ -1205,6 +1207,7 @@ def test_min_max_version(self):
ssl.TLSVersion.TLSv1,
ssl.TLSVersion.TLSv1_1,
ssl.TLSVersion.TLSv1_2,
ssl.TLSVersion.TLSv1_3,
ssl.TLSVersion.SSLv3,
}
)
Expand All @@ -1218,7 +1221,7 @@ def test_min_max_version(self):
with self.assertRaises(ValueError):
ctx.minimum_version = 42

if has_tls_protocol(ssl.PROTOCOL_TLSv1_1):
if has_tls_protocol('PROTOCOL_TLSv1_1'):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)

self.assertIn(
Expand Down Expand Up @@ -1675,23 +1678,24 @@ def test__create_stdlib_context(self):
self.assertFalse(ctx.check_hostname)
self._assert_context_options(ctx)

if has_tls_protocol(ssl.PROTOCOL_TLSv1):
if has_tls_protocol('PROTOCOL_TLSv1'):
with warnings_helper.check_warnings():
ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1)
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
self._assert_context_options(ctx)

with warnings_helper.check_warnings():
ctx = ssl._create_stdlib_context(
ssl.PROTOCOL_TLSv1_2,
cert_reqs=ssl.CERT_REQUIRED,
check_hostname=True
)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
self.assertTrue(ctx.check_hostname)
self._assert_context_options(ctx)
if has_tls_protocol('PROTOCOL_TLSv1_2'):
with warnings_helper.check_warnings():
ctx = ssl._create_stdlib_context(
ssl.PROTOCOL_TLSv1_2,
cert_reqs=ssl.CERT_REQUIRED,
check_hostname=True
)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1_2)
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
self.assertTrue(ctx.check_hostname)
self._assert_context_options(ctx)

ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH)
self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLS_SERVER)
Expand Down Expand Up @@ -3654,10 +3658,10 @@ def test_protocol_tlsv1_2(self):
client_options=ssl.OP_NO_TLSv1_2)

try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')
if has_tls_protocol(ssl.PROTOCOL_TLSv1):
if has_tls_protocol('PROTOCOL_TLSv1'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)
if has_tls_protocol(ssl.PROTOCOL_TLSv1_1):
if has_tls_protocol('PROTOCOL_TLSv1_1'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for OpenSSL 4.0.0 alpha1. Patch by Victor Stinner.
27 changes: 22 additions & 5 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ static void _PySSLFixErrno(void) {
#error Unsupported OpenSSL version
#endif

#if (OPENSSL_VERSION_NUMBER >= 0x40000000L)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it possible to retain those constants using the OpenSSL compatibility features or are these constants entirely gone?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 4 methods are gone but I cannot find OPENSSL_NO_ macro in the public header files:

$ nm multissl/openssl/4.0.0-alpha1/lib64/libssl.so.4 |grep SSLv3_method
$ nm multissl/openssl/4.0.0-alpha1/lib64/libssl.so.4 |grep TLSv1_method
$ nm multissl/openssl/4.0.0-alpha1/lib64/libssl.so.4 |grep TLSv1_1_method
$ nm multissl/openssl/4.0.0-alpha1/lib64/libssl.so.4 |grep TLSv1_2_method
$ grep OPENSSL_NO_SSL3 multissl/openssl/4.0.0-alpha1/include/openssl/ -R
$ grep OPENSSL_NO_TLS1 multissl/openssl/4.0.0-alpha1/include/openssl/ -R
$ grep OPENSSL_NO_TLS1_1 multissl/openssl/4.0.0-alpha1/include/openssl/ -R
$ grep OPENSSL_NO_TLS1_2 multissl/openssl/4.0.0-alpha1/include/openssl/ -R

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think more about it, I think those macros are defined by your build configuration and the generated headers. I never remember which macro is defined explicitly through other macros and which macros are defined dynamically after the configure step

# define OPENSSL_NO_SSL3
# define OPENSSL_NO_TLS1
# define OPENSSL_NO_TLS1_1
# define OPENSSL_NO_TLS1_2
# define OPENSSL_NO_SSL3_METHOD
# define OPENSSL_NO_TLS1_METHOD
# define OPENSSL_NO_TLS1_1_METHOD
# define OPENSSL_NO_TLS1_2_METHOD
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot comment on the lines above this block but we need to check if mnemonics changed in 4.0 as well and generate dedicated data. I would still generate dedicated data just because the major version was bumped.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect that OpenSSL will still change before the OpenSSL 4.0 final release. Can we wait for the final release before generating the "ssl data" header file?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we can.


/* OpenSSL API 1.1.0+ does not include version methods */
#ifndef OPENSSL_NO_SSL3_METHOD
extern const SSL_METHOD *SSLv3_method(void);
Expand Down Expand Up @@ -1151,7 +1162,7 @@ _asn1obj2py(_sslmodulestate *state, const ASN1_OBJECT *name, int no_name)

static PyObject *
_create_tuple_for_attribute(_sslmodulestate *state,
ASN1_OBJECT *name, ASN1_STRING *value)
const ASN1_OBJECT *name, const ASN1_STRING *value)
{
Py_ssize_t buflen;
PyObject *pyattr;
Expand Down Expand Up @@ -1180,16 +1191,16 @@ _create_tuple_for_attribute(_sslmodulestate *state,
}

static PyObject *
_create_tuple_for_X509_NAME (_sslmodulestate *state, X509_NAME *xname)
_create_tuple_for_X509_NAME(_sslmodulestate *state, const X509_NAME *xname)
{
PyObject *dn = NULL; /* tuple which represents the "distinguished name" */
PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */
PyObject *rdnt;
PyObject *attr = NULL; /* tuple to hold an attribute */
int entry_count = X509_NAME_entry_count(xname);
X509_NAME_ENTRY *entry;
ASN1_OBJECT *name;
ASN1_STRING *value;
const X509_NAME_ENTRY *entry;
const ASN1_OBJECT *name;
const ASN1_STRING *value;
int index_counter;
int rdn_level = -1;
int retcode;
Expand Down Expand Up @@ -6967,9 +6978,15 @@ sslmodule_init_constants(PyObject *m)
ADD_INT_CONST("PROTOCOL_TLS", PY_SSL_VERSION_TLS);
ADD_INT_CONST("PROTOCOL_TLS_CLIENT", PY_SSL_VERSION_TLS_CLIENT);
ADD_INT_CONST("PROTOCOL_TLS_SERVER", PY_SSL_VERSION_TLS_SERVER);
#ifndef OPENSSL_NO_TLS1
ADD_INT_CONST("PROTOCOL_TLSv1", PY_SSL_VERSION_TLS1);
#endif
#ifndef OPENSSL_NO_TLS1_1
ADD_INT_CONST("PROTOCOL_TLSv1_1", PY_SSL_VERSION_TLS1_1);
#endif
#ifndef OPENSSL_NO_TLS1_2
ADD_INT_CONST("PROTOCOL_TLSv1_2", PY_SSL_VERSION_TLS1_2);
#endif

#define ADD_OPTION(NAME, VALUE) if (sslmodule_add_option(m, NAME, (VALUE)) < 0) return -1

Expand Down
3 changes: 2 additions & 1 deletion Modules/_ssl/cert.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ _ssl_Certificate_get_info_impl(PySSLCertificate *self)
}

static PyObject*
_x509name_print(_sslmodulestate *state, X509_NAME *name, int indent, unsigned long flags)
_x509name_print(_sslmodulestate *state, const X509_NAME *name,
int indent, unsigned long flags)
{
PyObject *res;
BIO *biobuf;
Expand Down
4 changes: 2 additions & 2 deletions Tools/ssl/multissltests.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,11 +427,11 @@ class BuildOpenSSL(AbstractBuilder):
depend_target = 'depend'

def _post_install(self):
if self.version.startswith("3."):
if self.version.startswith(("3.", "4.")):
self._post_install_3xx()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the future, it is better to have two methods for post install, one for 3.x and one for 4.x

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the script does the same operations on OpenSSL 3 and OpenSSL 4. Is it worth it to have two methods which do the same operations?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say yes as we do not know what will be needed with 4.x (I do not mind having the 4xx call the 3xx with a comment saying that for now it is identical).

I will give you an answer about it once I looked at the OpenSSL roadmap so ok for leaving it that way for now.


def _build_src(self, config_args=()):
if self.version.startswith("3."):
if self.version.startswith(("3.", "4.")):
config_args += ("enable-fips",)
super()._build_src(config_args)

Expand Down
Loading