Skip to content

Commit f292b07

Browse files
authored
[3.11] gh-106687: _ssl: use uint64_t for SSL options (#106700) (#116665)
gh-106687: _ssl: use uint64_t for SSL options (#106700) SSL_CTX_get_options() uses uint64_t for options: https://www.openssl.org/docs/man3.1/man3/SSL_CTX_get_options.html Fix this compiler warning on Windows with MSC: conversion from 'uint64_t' to 'long', possible loss of data (cherry picked from commit ad95c72)
1 parent cde47e2 commit f292b07

File tree

2 files changed

+76
-24
lines changed

2 files changed

+76
-24
lines changed

Lib/test/test_ssl.py

+24
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,15 @@ def test_constants(self):
350350
ssl.OP_NO_TLSv1_2
351351
self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
352352

353+
def test_options(self):
354+
# gh-106687: SSL options values are unsigned integer (uint64_t)
355+
for name in dir(ssl):
356+
if not name.startswith('OP_'):
357+
continue
358+
with self.subTest(option=name):
359+
value = getattr(ssl, name)
360+
self.assertGreaterEqual(value, 0, f"ssl.{name}")
361+
353362
def test_ssl_types(self):
354363
ssl_types = [
355364
_ssl._SSLContext,
@@ -1197,6 +1206,7 @@ def test_get_ciphers(self):
11971206
)
11981207

11991208
def test_options(self):
1209+
# Test default SSLContext options
12001210
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
12011211
# OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
12021212
default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
@@ -1205,16 +1215,30 @@ def test_options(self):
12051215
OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
12061216
OP_ENABLE_MIDDLEBOX_COMPAT)
12071217
self.assertEqual(default, ctx.options)
1218+
1219+
# disallow TLSv1
12081220
with warnings_helper.check_warnings():
12091221
ctx.options |= ssl.OP_NO_TLSv1
12101222
self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
1223+
1224+
# allow TLSv1
12111225
with warnings_helper.check_warnings():
12121226
ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
12131227
self.assertEqual(default, ctx.options)
1228+
1229+
# clear all options
12141230
ctx.options = 0
12151231
# Ubuntu has OP_NO_SSLv3 forced on by default
12161232
self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
12171233

1234+
# invalid options
1235+
with self.assertRaises(OverflowError):
1236+
ctx.options = -1
1237+
with self.assertRaises(OverflowError):
1238+
ctx.options = 2 ** 100
1239+
with self.assertRaises(TypeError):
1240+
ctx.options = "abc"
1241+
12181242
def test_verify_mode_protocol(self):
12191243
with warnings_helper.check_warnings():
12201244
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)

Modules/_ssl.c

+52-24
Original file line numberDiff line numberDiff line change
@@ -3023,7 +3023,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
30233023
/*[clinic end generated code: output=2cf0d7a0741b6bd1 input=8d58a805b95fc534]*/
30243024
{
30253025
PySSLContext *self;
3026-
long options;
3026+
uint64_t options;
30273027
const SSL_METHOD *method = NULL;
30283028
SSL_CTX *ctx = NULL;
30293029
X509_VERIFY_PARAM *params;
@@ -3621,20 +3621,32 @@ PyDoc_STRVAR(PySSLContext_security_level_doc, "The current security level");
36213621
static PyObject *
36223622
get_options(PySSLContext *self, void *c)
36233623
{
3624-
return PyLong_FromLong(SSL_CTX_get_options(self->ctx));
3624+
uint64_t options = SSL_CTX_get_options(self->ctx);
3625+
Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(options));
3626+
return PyLong_FromUnsignedLongLong(options);
36253627
}
36263628

36273629
static int
36283630
set_options(PySSLContext *self, PyObject *arg, void *c)
36293631
{
3630-
long new_opts, opts, set, clear;
3631-
long opt_no = (
3632+
PyObject *new_opts_obj;
3633+
unsigned long long new_opts_arg;
3634+
uint64_t new_opts, opts, clear, set;
3635+
uint64_t opt_no = (
36323636
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |
36333637
SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3
36343638
);
36353639

3636-
if (!PyArg_Parse(arg, "l", &new_opts))
3640+
if (!PyArg_Parse(arg, "O!", &PyLong_Type, &new_opts_obj)) {
36373641
return -1;
3642+
}
3643+
new_opts_arg = PyLong_AsUnsignedLongLong(new_opts_obj);
3644+
if (new_opts_arg == (unsigned long long)-1 && PyErr_Occurred()) {
3645+
return -1;
3646+
}
3647+
Py_BUILD_ASSERT(sizeof(new_opts) >= sizeof(new_opts_arg));
3648+
new_opts = (uint64_t)new_opts_arg;
3649+
36383650
opts = SSL_CTX_get_options(self->ctx);
36393651
clear = opts & ~new_opts;
36403652
set = ~opts & new_opts;
@@ -3648,8 +3660,9 @@ set_options(PySSLContext *self, PyObject *arg, void *c)
36483660
if (clear) {
36493661
SSL_CTX_clear_options(self->ctx, clear);
36503662
}
3651-
if (set)
3663+
if (set) {
36523664
SSL_CTX_set_options(self->ctx, set);
3665+
}
36533666
return 0;
36543667
}
36553668

@@ -5835,10 +5848,24 @@ sslmodule_init_socketapi(PyObject *module)
58355848
return 0;
58365849
}
58375850

5851+
58385852
static int
5839-
sslmodule_init_constants(PyObject *m)
5853+
sslmodule_add_option(PyObject *m, const char *name, uint64_t value)
58405854
{
5855+
Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(value));
5856+
PyObject *obj = PyLong_FromUnsignedLongLong(value);
5857+
if (obj == NULL) {
5858+
return -1;
5859+
}
5860+
int res = PyModule_AddObjectRef(m, name, obj);
5861+
Py_DECREF(obj);
5862+
return res;
5863+
}
5864+
58415865

5866+
static int
5867+
sslmodule_init_constants(PyObject *m)
5868+
{
58425869
PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS",
58435870
PY_SSL_DEFAULT_CIPHER_STRING);
58445871

@@ -5962,40 +5989,41 @@ sslmodule_init_constants(PyObject *m)
59625989
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_2",
59635990
PY_SSL_VERSION_TLS1_2);
59645991

5992+
#define ADD_OPTION(NAME, VALUE) if (sslmodule_add_option(m, NAME, (VALUE)) < 0) return -1
5993+
59655994
/* protocol options */
5966-
PyModule_AddIntConstant(m, "OP_ALL",
5967-
SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
5968-
PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2);
5969-
PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3);
5970-
PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);
5971-
PyModule_AddIntConstant(m, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
5972-
PyModule_AddIntConstant(m, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
5995+
ADD_OPTION("OP_ALL", SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
5996+
ADD_OPTION("OP_NO_SSLv2", SSL_OP_NO_SSLv2);
5997+
ADD_OPTION("OP_NO_SSLv3", SSL_OP_NO_SSLv3);
5998+
ADD_OPTION("OP_NO_TLSv1", SSL_OP_NO_TLSv1);
5999+
ADD_OPTION("OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
6000+
ADD_OPTION("OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
59736001
#ifdef SSL_OP_NO_TLSv1_3
5974-
PyModule_AddIntConstant(m, "OP_NO_TLSv1_3", SSL_OP_NO_TLSv1_3);
6002+
ADD_OPTION("OP_NO_TLSv1_3", SSL_OP_NO_TLSv1_3);
59756003
#else
5976-
PyModule_AddIntConstant(m, "OP_NO_TLSv1_3", 0);
6004+
ADD_OPTION("OP_NO_TLSv1_3", 0);
59776005
#endif
5978-
PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE",
6006+
ADD_OPTION("OP_CIPHER_SERVER_PREFERENCE",
59796007
SSL_OP_CIPHER_SERVER_PREFERENCE);
5980-
PyModule_AddIntConstant(m, "OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE);
5981-
PyModule_AddIntConstant(m, "OP_NO_TICKET", SSL_OP_NO_TICKET);
6008+
ADD_OPTION("OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE);
6009+
ADD_OPTION("OP_NO_TICKET", SSL_OP_NO_TICKET);
59826010
#ifdef SSL_OP_SINGLE_ECDH_USE
5983-
PyModule_AddIntConstant(m, "OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE);
6011+
ADD_OPTION("OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE);
59846012
#endif
59856013
#ifdef SSL_OP_NO_COMPRESSION
5986-
PyModule_AddIntConstant(m, "OP_NO_COMPRESSION",
6014+
ADD_OPTION("OP_NO_COMPRESSION",
59876015
SSL_OP_NO_COMPRESSION);
59886016
#endif
59896017
#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
5990-
PyModule_AddIntConstant(m, "OP_ENABLE_MIDDLEBOX_COMPAT",
6018+
ADD_OPTION("OP_ENABLE_MIDDLEBOX_COMPAT",
59916019
SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
59926020
#endif
59936021
#ifdef SSL_OP_NO_RENEGOTIATION
5994-
PyModule_AddIntConstant(m, "OP_NO_RENEGOTIATION",
6022+
ADD_OPTION("OP_NO_RENEGOTIATION",
59956023
SSL_OP_NO_RENEGOTIATION);
59966024
#endif
59976025
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
5998-
PyModule_AddIntConstant(m, "OP_IGNORE_UNEXPECTED_EOF",
6026+
ADD_OPTION("OP_IGNORE_UNEXPECTED_EOF",
59996027
SSL_OP_IGNORE_UNEXPECTED_EOF);
60006028
#endif
60016029

0 commit comments

Comments
 (0)