Skip to content

Commit 7d54ba5

Browse files
Fix ssl-vendor (OpenSSL) (RustPython#7985)
Closes: RustPython#7893 Fix 1: `foreign-types-shared` needs to match `openssl`'s version. Bumping it is a SemVer violation because the latest versions of the crate aren't backwards compatible with older versions. See: rust-openssl/rust-openssl#2461 Fix 2: The second fix is to align the `openssl` module with the latest `host_env` and `ssl` changes.
1 parent e80a14b commit 7d54ba5

4 files changed

Lines changed: 44 additions & 33 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ jobs:
140140
run: cargo build --no-default-features --features ssl-openssl
141141
if: runner.os == 'Linux'
142142

143+
- name: Test vendored OpenSSL build
144+
run: cargo build --no-default-features --features ssl-vendor
145+
if: runner.os == 'Linux'
146+
143147
# - name: Install tk-dev for tkinter build
144148
# run: sudo apt-get update && sudo apt-get install -y tk-dev
145149
# if: runner.os == 'Linux'

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ exitcode = "1.1.2"
217217
flame = "0.2.2"
218218
flamer = "0.5"
219219
flate2 = { version = "1.1.9", default-features = false }
220+
# Bump only when the openssl crate bumps it
220221
foreign-types-shared = "0.1"
221222
gethostname = "1.0.2"
222223
getrandom = { version = "0.3", features = ["std"] }

crates/stdlib/src/openssl.rs

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ mod _ssl {
6565
LazyLock, PyMappedRwLockReadGuard, PyMutex, PyRwLock, PyRwLockReadGuard,
6666
PyRwLockWriteGuard,
6767
},
68-
socket::{self, PySocket},
68+
socket::{self, PySocket, SockWaitKind, sock_wait},
6969
vm::{
7070
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
7171
builtins::{
@@ -2297,49 +2297,47 @@ mod _ssl {
22972297
needs: SslNeeds,
22982298
deadline: &SocketDeadline,
22992299
vm: &VirtualMachine,
2300-
) -> SelectRet {
2301-
let sock = match self.0.sock_opt() {
2302-
Some(s) => s,
2303-
None => return SelectRet::Closed,
2300+
) -> PyResult<SelectRet> {
2301+
let Some(sock) = self.0.sock_opt() else {
2302+
return Ok(SelectRet::Closed);
23042303
};
2305-
// For blocking sockets without timeout, call sock_wait with None timeout
2304+
// For blocking sockets without timeout, call sock_select with None timeout
23062305
// to actually block waiting for data instead of busy-looping
23072306
let timeout = match &deadline {
23082307
Ok(deadline) => match deadline.checked_duration_since(Instant::now()) {
23092308
Some(d) => Some(d),
2310-
None => return SelectRet::TimedOut,
2309+
None => return Ok(SelectRet::TimedOut),
23112310
},
23122311
Err(true) => None, // Blocking: no timeout, wait indefinitely
2313-
Err(false) => return SelectRet::Nonblocking,
2312+
Err(false) => return Ok(SelectRet::Nonblocking),
23142313
};
2315-
let res = socket::sock_wait(
2316-
&sock,
2317-
match needs {
2318-
SslNeeds::Read => socket::SockWaitKind::Read,
2319-
SslNeeds::Write => socket::SockWaitKind::Write,
2320-
},
2321-
timeout,
2322-
vm,
2323-
);
2324-
match res {
2325-
Ok(true) => SelectRet::TimedOut,
2326-
_ => SelectRet::Ok,
2327-
}
2314+
let wait_kind = match needs {
2315+
SslNeeds::Read => SockWaitKind::Read,
2316+
SslNeeds::Write => SockWaitKind::Write,
2317+
};
2318+
sock_wait(&*sock, wait_kind, timeout, vm).map(|timed_out| {
2319+
if timed_out {
2320+
SelectRet::TimedOut
2321+
} else {
2322+
SelectRet::Ok
2323+
}
2324+
})
23282325
}
23292326

23302327
fn socket_needs(
23312328
&self,
23322329
err: &ssl::Error,
23332330
deadline: &SocketDeadline,
23342331
vm: &VirtualMachine,
2335-
) -> (Option<SslNeeds>, SelectRet) {
2332+
) -> PyResult<(Option<SslNeeds>, SelectRet)> {
23362333
let needs = match err.code() {
23372334
ssl::ErrorCode::WANT_READ => Some(SslNeeds::Read),
23382335
ssl::ErrorCode::WANT_WRITE => Some(SslNeeds::Write),
23392336
_ => None,
23402337
};
2341-
let state = needs.map_or(SelectRet::Ok, |needs| self.select(needs, deadline, vm));
2342-
(needs, state)
2338+
let state =
2339+
needs.map_or(Ok(SelectRet::Ok), |needs| self.select(needs, deadline, vm))?;
2340+
Ok((needs, state))
23432341
}
23442342
}
23452343

@@ -2857,7 +2855,7 @@ mod _ssl {
28572855
break;
28582856
}
28592857
// Wait briefly for peer's close_notify before retrying
2860-
match socket_stream.select(SslNeeds::Read, &deadline, vm) {
2858+
match socket_stream.select(SslNeeds::Read, &deadline, vm)? {
28612859
SelectRet::TimedOut => {
28622860
return Err(socket::timeout_error_msg(
28632861
vm,
@@ -2895,7 +2893,7 @@ mod _ssl {
28952893
};
28962894

28972895
// Wait on the socket
2898-
match socket_stream.select(needs, &deadline, vm) {
2896+
match socket_stream.select(needs, &deadline, vm)? {
28992897
SelectRet::TimedOut => {
29002898
let msg = if err == sys::SSL_ERROR_WANT_READ {
29012899
"The read operation timed out"
@@ -2991,7 +2989,7 @@ mod _ssl {
29912989
let (needs, state) = stream
29922990
.get_ref()
29932991
.expect("handshake called in bio mode; should only be called in socket mode")
2994-
.socket_needs(&err, &timeout, vm);
2992+
.socket_needs(&err, &timeout, vm)?;
29952993
match state {
29962994
SelectRet::TimedOut => {
29972995
// Clean up SNI ex_data before returning error
@@ -3045,7 +3043,7 @@ mod _ssl {
30453043
.get_ref()
30463044
.expect("write called in bio mode; should only be called in socket mode");
30473045
let timeout = socket_ref.timeout_deadline();
3048-
let state = socket_ref.select(SslNeeds::Write, &timeout, vm);
3046+
let state = socket_ref.select(SslNeeds::Write, &timeout, vm)?;
30493047
match state {
30503048
SelectRet::TimedOut => {
30513049
return Err(socket::timeout_error_msg(
@@ -3065,7 +3063,7 @@ mod _ssl {
30653063
let (needs, state) = stream
30663064
.get_ref()
30673065
.expect("write called in bio mode; should only be called in socket mode")
3068-
.socket_needs(&err, &timeout, vm);
3066+
.socket_needs(&err, &timeout, vm)?;
30693067
match state {
30703068
SelectRet::TimedOut => {
30713069
return Err(socket::timeout_error_msg(
@@ -3236,7 +3234,7 @@ mod _ssl {
32363234
let (needs, state) = stream
32373235
.get_ref()
32383236
.expect("read called in bio mode; should only be called in socket mode")
3239-
.socket_needs(&err, &timeout, vm);
3237+
.socket_needs(&err, &timeout, vm)?;
32403238
match state {
32413239
SelectRet::TimedOut => {
32423240
return Err(socket::timeout_error_msg(
@@ -4149,7 +4147,7 @@ mod bio {
41494147
use openssl_sys as sys;
41504148
use std::marker::PhantomData;
41514149

4152-
pub struct MemBioSlice<'a>(*mut sys::BIO, PhantomData<&'a [u8]>);
4150+
pub(super) struct MemBioSlice<'a>(*mut sys::BIO, PhantomData<&'a [u8]>);
41534151

41544152
impl Drop for MemBioSlice<'_> {
41554153
fn drop(&mut self) {
@@ -4160,7 +4158,7 @@ mod bio {
41604158
}
41614159

41624160
impl<'a> MemBioSlice<'a> {
4163-
pub fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
4161+
pub(super) fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
41644162
openssl::init();
41654163

41664164
assert!(buf.len() <= c_int::MAX as usize);
@@ -4172,7 +4170,7 @@ mod bio {
41724170
Ok(MemBioSlice(bio, PhantomData))
41734171
}
41744172

4175-
pub fn as_ptr(&self) -> *mut sys::BIO {
4173+
pub(super) fn as_ptr(&self) -> *mut sys::BIO {
41764174
self.0
41774175
}
41784176
}

crates/stdlib/src/ssl/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ pub(crate) mod ssl_error {
125125
)
126126
}
127127

128+
#[cfg_attr(
129+
all(feature = "ssl-openssl", not(feature = "ssl-rustls")),
130+
expect(dead_code)
131+
)]
128132
pub(crate) fn create_ssl_zero_return_error(vm: &VirtualMachine) -> PyRef<PyOSError> {
129133
vm.new_os_subtype_error(
130134
PySSLZeroReturnError::class(&vm.ctx).to_owned(),
@@ -133,6 +137,10 @@ pub(crate) mod ssl_error {
133137
)
134138
}
135139

140+
#[cfg_attr(
141+
all(feature = "ssl-openssl", not(feature = "ssl-rustls")),
142+
expect(dead_code)
143+
)]
136144
pub(crate) fn create_ssl_syscall_error(
137145
vm: &VirtualMachine,
138146
msg: impl Into<String>,

0 commit comments

Comments
 (0)