Skip to content

Commit 249ae08

Browse files
authored
fix(ssl): emit missing deprecation warnings (RustPython#8418)
Assisted-by: Codex:gpt-5.6-sol
1 parent 05f7f74 commit 249ae08

3 files changed

Lines changed: 93 additions & 17 deletions

File tree

Lib/test/test_ssl.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,6 @@ def test_timeout(self):
650650
with test_wrap_socket(s) as ss:
651651
self.assertEqual(timeout, ss.gettimeout())
652652

653-
@unittest.expectedFailure # TODO: RUSTPYTHON
654653
def test_openssl111_deprecations(self):
655654
options = [
656655
ssl.OP_NO_TLSv1,

crates/stdlib/src/openssl.rs

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ mod _ssl {
8181
ArgBytesLike, ArgMemoryBuffer, ArgStrOrBytesLike, Either, FsPath, OptionalArg,
8282
PyComparisonValue,
8383
},
84+
stdlib::_warnings,
8485
types::{Comparable, Constructor, PyComparisonOp},
8586
utils::ToCString,
8687
},
@@ -914,16 +915,24 @@ mod _ssl {
914915
) -> PyResult<Self> {
915916
let proto = SslVersion::try_from(proto_version)
916917
.map_err(|_| vm.new_value_error("invalid protocol version"))?;
917-
let method = match proto {
918+
let (method, deprecated_protocol) = match proto {
918919
// SslVersion::Ssl3 => unsafe { ssl::SslMethod::from_ptr(sys::SSLv3_method()) },
919-
SslVersion::Tls => ssl::SslMethod::tls(),
920-
SslVersion::Tls1 => ssl::SslMethod::tls(),
921-
SslVersion::Tls1_1 => ssl::SslMethod::tls(),
922-
SslVersion::Tls1_2 => ssl::SslMethod::tls(),
923-
SslVersion::TlsClient => ssl::SslMethod::tls_client(),
924-
SslVersion::TlsServer => ssl::SslMethod::tls_server(),
920+
SslVersion::Tls => (ssl::SslMethod::tls(), Some("PROTOCOL_TLS")),
921+
SslVersion::Tls1 => (ssl::SslMethod::tls(), Some("PROTOCOL_TLSv1")),
922+
SslVersion::Tls1_1 => (ssl::SslMethod::tls(), Some("PROTOCOL_TLSv1_1")),
923+
SslVersion::Tls1_2 => (ssl::SslMethod::tls(), Some("PROTOCOL_TLSv1_2")),
924+
SslVersion::TlsClient => (ssl::SslMethod::tls_client(), None),
925+
SslVersion::TlsServer => (ssl::SslMethod::tls_server(), None),
925926
_ => return Err(vm.new_value_error("invalid protocol version")),
926927
};
928+
if let Some(protocol_name) = deprecated_protocol {
929+
_warnings::warn(
930+
vm.ctx.exceptions.deprecation_warning,
931+
format!("ssl.{protocol_name} is deprecated"),
932+
2,
933+
vm,
934+
)?;
935+
}
927936
let mut builder =
928937
SslContextBuilder::new(method).map_err(|e| convert_openssl_error(vm, e))?;
929938

@@ -1012,6 +1021,24 @@ mod _ssl {
10121021

10131022
#[pyclass(flags(BASETYPE, IMMUTABLETYPE), with(Constructor))]
10141023
impl PySslContext {
1024+
fn warn_deprecated_tls_version(version: i32, vm: &VirtualMachine) -> PyResult<()> {
1025+
let version_name = match version {
1026+
PROTO_SSLv3 => Some("SSLv3"),
1027+
PROTO_TLSv1 => Some("TLSv1"),
1028+
PROTO_TLSv1_1 => Some("TLSv1_1"),
1029+
_ => None,
1030+
};
1031+
if let Some(version_name) = version_name {
1032+
_warnings::warn(
1033+
vm.ctx.exceptions.deprecation_warning,
1034+
format!("ssl.TLSVersion.{version_name} is deprecated"),
1035+
2,
1036+
vm,
1037+
)?;
1038+
}
1039+
Ok(())
1040+
}
1041+
10151042
fn builder(&self) -> PyRwLockWriteGuard<'_, SslContextBuilder> {
10161043
self.ctx.write()
10171044
}
@@ -1133,14 +1160,32 @@ mod _ssl {
11331160
return Err(vm.new_value_error("invalid options value"));
11341161
}
11351162
let new_opts = new_opts as core::ffi::c_ulong;
1136-
let mut ctx = self.builder();
1137-
// Get current options
1138-
let current = ctx.options().bits() as core::ffi::c_ulong;
1163+
let current = {
1164+
let ctx = self.ctx();
1165+
unsafe { sys::SSL_CTX_get_options(ctx.as_ptr()) }
1166+
};
11391167

11401168
// Calculate options to clear and set
11411169
let clear = current & !new_opts;
11421170
let set = !current & new_opts;
11431171

1172+
let opt_no = sys::SSL_OP_NO_SSLv2
1173+
| sys::SSL_OP_NO_SSLv3
1174+
| sys::SSL_OP_NO_TLSv1
1175+
| sys::SSL_OP_NO_TLSv1_1
1176+
| sys::SSL_OP_NO_TLSv1_2;
1177+
#[cfg(ossl111)]
1178+
let opt_no = opt_no | sys::SSL_OP_NO_TLSv1_3;
1179+
if (set & opt_no) != 0 {
1180+
_warnings::warn(
1181+
vm.ctx.exceptions.deprecation_warning,
1182+
"ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated".to_owned(),
1183+
2,
1184+
vm,
1185+
)?;
1186+
}
1187+
1188+
let mut ctx = self.builder();
11441189
// Clear options first (using raw FFI since openssl crate doesn't expose clear_options)
11451190
if clear != 0 {
11461191
unsafe {
@@ -1247,6 +1292,8 @@ mod _ssl {
12471292
}
12481293
#[pygetset(setter)]
12491294
fn set_minimum_version(&self, value: i32, vm: &VirtualMachine) -> PyResult<()> {
1295+
Self::warn_deprecated_tls_version(value, vm)?;
1296+
12501297
// Handle special values
12511298
let proto_version = match value {
12521299
-2 => {
@@ -1281,6 +1328,8 @@ mod _ssl {
12811328
}
12821329
#[pygetset(setter)]
12831330
fn set_maximum_version(&self, value: i32, vm: &VirtualMachine) -> PyResult<()> {
1331+
Self::warn_deprecated_tls_version(value, vm)?;
1332+
12841333
// Handle special values
12851334
let proto_version = match value {
12861335
-1 => {

crates/stdlib/src/ssl.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,24 @@ mod _ssl {
881881

882882
#[pyclass(with(Constructor, Representable), flags(BASETYPE))]
883883
impl PySSLContext {
884+
fn warn_deprecated_tls_version(version: i32, vm: &VirtualMachine) -> PyResult<()> {
885+
let version_name = match version {
886+
PROTO_SSLv3 => Some("SSLv3"),
887+
PROTO_TLSv1 => Some("TLSv1"),
888+
PROTO_TLSv1_1 => Some("TLSv1_1"),
889+
_ => None,
890+
};
891+
if let Some(version_name) = version_name {
892+
_warnings::warn(
893+
vm.ctx.exceptions.deprecation_warning,
894+
format!("ssl.TLSVersion.{version_name} is deprecated"),
895+
2,
896+
vm,
897+
)?;
898+
}
899+
Ok(())
900+
}
901+
884902
// Helper method to convert DER certificate bytes to Python dict
885903
fn cert_der_to_dict(&self, vm: &VirtualMachine, cert_der: &[u8]) -> PyResult<PyObjectRef> {
886904
cert::cert_der_to_dict_helper(vm, cert_der)
@@ -1024,6 +1042,8 @@ mod _ssl {
10241042
{
10251043
return Err(vm.new_value_error(format!("invalid protocol version: {value}")));
10261044
}
1045+
Self::warn_deprecated_tls_version(value, vm)?;
1046+
10271047
// Convert special values to rustls actual supported versions
10281048
// MINIMUM_SUPPORTED (-2) -> 0 (auto-negotiate)
10291049
// MAXIMUM_SUPPORTED (-1) -> MAXIMUM_VERSION (TLSv1.3)
@@ -1055,6 +1075,8 @@ mod _ssl {
10551075
{
10561076
return Err(vm.new_value_error(format!("invalid protocol version: {value}")));
10571077
}
1078+
Self::warn_deprecated_tls_version(value, vm)?;
1079+
10581080
// Convert special values to rustls actual supported versions
10591081
// MAXIMUM_SUPPORTED (-1) -> 0 (auto-negotiate)
10601082
// MINIMUM_SUPPORTED (-2) -> MINIMUM_VERSION (TLSv1.2)
@@ -2214,12 +2236,10 @@ mod _ssl {
22142236
) -> PyResult<Self> {
22152237
let crypto_ext = CryptoExt::get_ext();
22162238

2217-
// Validate protocol
2218-
match protocol {
2219-
PROTOCOL_TLS | PROTOCOL_TLS_CLIENT | PROTOCOL_TLS_SERVER | PROTOCOL_TLSv1_2
2220-
| PROTOCOL_TLSv1_3 => {
2221-
// Valid protocols
2222-
}
2239+
let deprecated_protocol = match protocol {
2240+
PROTOCOL_TLS => Some("PROTOCOL_TLS"),
2241+
PROTOCOL_TLSv1_2 => Some("PROTOCOL_TLSv1_2"),
2242+
PROTOCOL_TLS_CLIENT | PROTOCOL_TLS_SERVER | PROTOCOL_TLSv1_3 => None,
22232243
PROTOCOL_TLSv1 | PROTOCOL_TLSv1_1 => {
22242244
return Err(vm.new_value_error(
22252245
"TLS 1.0 and 1.1 are not supported by rustls for security reasons",
@@ -2228,6 +2248,14 @@ mod _ssl {
22282248
_ => {
22292249
return Err(vm.new_value_error(format!("invalid protocol version: {protocol}")));
22302250
}
2251+
};
2252+
if let Some(protocol_name) = deprecated_protocol {
2253+
_warnings::warn(
2254+
vm.ctx.exceptions.deprecation_warning,
2255+
format!("ssl.{protocol_name} is deprecated"),
2256+
2,
2257+
vm,
2258+
)?;
22312259
}
22322260

22332261
// Set default options

0 commit comments

Comments
 (0)