mirror of https://github.com/python/cpython
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
This commit is contained in:
parent
036bb73656
commit
ad95c7253a
|
@ -339,6 +339,15 @@ class BasicSocketTests(unittest.TestCase):
|
|||
ssl.OP_NO_TLSv1_2
|
||||
self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23)
|
||||
|
||||
def test_options(self):
|
||||
# gh-106687: SSL options values are unsigned integer (uint64_t)
|
||||
for name in dir(ssl):
|
||||
if not name.startswith('OP_'):
|
||||
continue
|
||||
with self.subTest(option=name):
|
||||
value = getattr(ssl, name)
|
||||
self.assertGreaterEqual(value, 0, f"ssl.{name}")
|
||||
|
||||
def test_ssl_types(self):
|
||||
ssl_types = [
|
||||
_ssl._SSLContext,
|
||||
|
@ -951,6 +960,7 @@ class ContextTests(unittest.TestCase):
|
|||
)
|
||||
|
||||
def test_options(self):
|
||||
# Test default SSLContext options
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
# OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
|
||||
default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
|
||||
|
@ -959,16 +969,30 @@ class ContextTests(unittest.TestCase):
|
|||
OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE |
|
||||
OP_ENABLE_MIDDLEBOX_COMPAT)
|
||||
self.assertEqual(default, ctx.options)
|
||||
|
||||
# disallow TLSv1
|
||||
with warnings_helper.check_warnings():
|
||||
ctx.options |= ssl.OP_NO_TLSv1
|
||||
self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
|
||||
|
||||
# allow TLSv1
|
||||
with warnings_helper.check_warnings():
|
||||
ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
|
||||
self.assertEqual(default, ctx.options)
|
||||
|
||||
# clear all options
|
||||
ctx.options = 0
|
||||
# Ubuntu has OP_NO_SSLv3 forced on by default
|
||||
self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
|
||||
|
||||
# invalid options
|
||||
with self.assertRaises(OverflowError):
|
||||
ctx.options = -1
|
||||
with self.assertRaises(OverflowError):
|
||||
ctx.options = 2 ** 100
|
||||
with self.assertRaises(TypeError):
|
||||
ctx.options = "abc"
|
||||
|
||||
def test_verify_mode_protocol(self):
|
||||
with warnings_helper.check_warnings():
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
||||
|
|
|
@ -3025,7 +3025,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
|
|||
/*[clinic end generated code: output=2cf0d7a0741b6bd1 input=8d58a805b95fc534]*/
|
||||
{
|
||||
PySSLContext *self;
|
||||
long options;
|
||||
uint64_t options;
|
||||
const SSL_METHOD *method = NULL;
|
||||
SSL_CTX *ctx = NULL;
|
||||
X509_VERIFY_PARAM *params;
|
||||
|
@ -3618,20 +3618,32 @@ PyDoc_STRVAR(PySSLContext_security_level_doc, "The current security level");
|
|||
static PyObject *
|
||||
get_options(PySSLContext *self, void *c)
|
||||
{
|
||||
return PyLong_FromLong(SSL_CTX_get_options(self->ctx));
|
||||
uint64_t options = SSL_CTX_get_options(self->ctx);
|
||||
Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(options));
|
||||
return PyLong_FromUnsignedLongLong(options);
|
||||
}
|
||||
|
||||
static int
|
||||
set_options(PySSLContext *self, PyObject *arg, void *c)
|
||||
{
|
||||
long new_opts, opts, set, clear;
|
||||
long opt_no = (
|
||||
PyObject *new_opts_obj;
|
||||
unsigned long long new_opts_arg;
|
||||
uint64_t new_opts, opts, clear, set;
|
||||
uint64_t opt_no = (
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |
|
||||
SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3
|
||||
);
|
||||
|
||||
if (!PyArg_Parse(arg, "l", &new_opts))
|
||||
if (!PyArg_Parse(arg, "O!", &PyLong_Type, &new_opts_obj)) {
|
||||
return -1;
|
||||
}
|
||||
new_opts_arg = PyLong_AsUnsignedLongLong(new_opts_obj);
|
||||
if (new_opts_arg == (unsigned long long)-1 && PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
Py_BUILD_ASSERT(sizeof(new_opts) >= sizeof(new_opts_arg));
|
||||
new_opts = (uint64_t)new_opts_arg;
|
||||
|
||||
opts = SSL_CTX_get_options(self->ctx);
|
||||
clear = opts & ~new_opts;
|
||||
set = ~opts & new_opts;
|
||||
|
@ -3645,8 +3657,9 @@ set_options(PySSLContext *self, PyObject *arg, void *c)
|
|||
if (clear) {
|
||||
SSL_CTX_clear_options(self->ctx, clear);
|
||||
}
|
||||
if (set)
|
||||
if (set) {
|
||||
SSL_CTX_set_options(self->ctx, set);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5754,10 +5767,24 @@ sslmodule_init_socketapi(PyObject *module)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sslmodule_add_option(PyObject *m, const char *name, uint64_t value)
|
||||
{
|
||||
Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(value));
|
||||
PyObject *obj = PyLong_FromUnsignedLongLong(value);
|
||||
if (obj == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int res = PyModule_AddObjectRef(m, name, obj);
|
||||
Py_DECREF(obj);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sslmodule_init_constants(PyObject *m)
|
||||
{
|
||||
|
||||
PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS",
|
||||
PY_SSL_DEFAULT_CIPHER_STRING);
|
||||
|
||||
|
@ -5877,46 +5904,47 @@ sslmodule_init_constants(PyObject *m)
|
|||
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_2",
|
||||
PY_SSL_VERSION_TLS1_2);
|
||||
|
||||
#define ADD_OPTION(NAME, VALUE) if (sslmodule_add_option(m, NAME, (VALUE)) < 0) return -1
|
||||
|
||||
/* protocol options */
|
||||
PyModule_AddIntConstant(m, "OP_ALL",
|
||||
SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
|
||||
PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2);
|
||||
PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3);
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
|
||||
ADD_OPTION("OP_ALL", SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
|
||||
ADD_OPTION("OP_NO_SSLv2", SSL_OP_NO_SSLv2);
|
||||
ADD_OPTION("OP_NO_SSLv3", SSL_OP_NO_SSLv3);
|
||||
ADD_OPTION("OP_NO_TLSv1", SSL_OP_NO_TLSv1);
|
||||
ADD_OPTION("OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
|
||||
ADD_OPTION("OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
|
||||
#ifdef SSL_OP_NO_TLSv1_3
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1_3", SSL_OP_NO_TLSv1_3);
|
||||
ADD_OPTION("OP_NO_TLSv1_3", SSL_OP_NO_TLSv1_3);
|
||||
#else
|
||||
PyModule_AddIntConstant(m, "OP_NO_TLSv1_3", 0);
|
||||
ADD_OPTION("OP_NO_TLSv1_3", 0);
|
||||
#endif
|
||||
PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE",
|
||||
ADD_OPTION("OP_CIPHER_SERVER_PREFERENCE",
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
PyModule_AddIntConstant(m, "OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE);
|
||||
PyModule_AddIntConstant(m, "OP_NO_TICKET", SSL_OP_NO_TICKET);
|
||||
PyModule_AddIntConstant(m, "OP_LEGACY_SERVER_CONNECT",
|
||||
ADD_OPTION("OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE);
|
||||
ADD_OPTION("OP_NO_TICKET", SSL_OP_NO_TICKET);
|
||||
ADD_OPTION("OP_LEGACY_SERVER_CONNECT",
|
||||
SSL_OP_LEGACY_SERVER_CONNECT);
|
||||
#ifdef SSL_OP_SINGLE_ECDH_USE
|
||||
PyModule_AddIntConstant(m, "OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE);
|
||||
ADD_OPTION("OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE);
|
||||
#endif
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
PyModule_AddIntConstant(m, "OP_NO_COMPRESSION",
|
||||
ADD_OPTION("OP_NO_COMPRESSION",
|
||||
SSL_OP_NO_COMPRESSION);
|
||||
#endif
|
||||
#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
|
||||
PyModule_AddIntConstant(m, "OP_ENABLE_MIDDLEBOX_COMPAT",
|
||||
ADD_OPTION("OP_ENABLE_MIDDLEBOX_COMPAT",
|
||||
SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
|
||||
#endif
|
||||
#ifdef SSL_OP_NO_RENEGOTIATION
|
||||
PyModule_AddIntConstant(m, "OP_NO_RENEGOTIATION",
|
||||
ADD_OPTION("OP_NO_RENEGOTIATION",
|
||||
SSL_OP_NO_RENEGOTIATION);
|
||||
#endif
|
||||
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
|
||||
PyModule_AddIntConstant(m, "OP_IGNORE_UNEXPECTED_EOF",
|
||||
ADD_OPTION("OP_IGNORE_UNEXPECTED_EOF",
|
||||
SSL_OP_IGNORE_UNEXPECTED_EOF);
|
||||
#endif
|
||||
#ifdef SSL_OP_ENABLE_KTLS
|
||||
PyModule_AddIntConstant(m, "OP_ENABLE_KTLS", SSL_OP_ENABLE_KTLS);
|
||||
ADD_OPTION("OP_ENABLE_KTLS", SSL_OP_ENABLE_KTLS);
|
||||
#endif
|
||||
|
||||
#ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
|
||||
|
|
Loading…
Reference in New Issue