Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1fc51ef

Browse files
reaperhulkclaude
andauthored
openssl 4 support (#2591)
* Add initial support for OpenSSL 4.x betas Accept OpenSSL 4.x in the version check (raising the ceiling to 4.0.0 final), add the ossl400 cfg flag, and ignore tests with behavioral changes in OpenSSL 4 (tmp_dh_callback, zero_length_buffers). * Fix zero-length SSL_read_ex/SSL_write_ex calling into OpenSSL The empty-buffer early return was only on the pre-1.1.1 code path. On the ossl111/libressl path, SSL_read_ex and SSL_write_ex were called with length 0, causing OpenSSL to perform wire I/O unnecessarily. This was exposed by OpenSSL 4 which now errors. Hoist the guard above the cfg_if so it applies to all versions. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * Handle const-qualified return types in OpenSSL 4 OpenSSL 4 changed X509_NAME_ENTRY_get_data, X509_NAME_ENTRY_get_object, and X509_CRL_get_issuer to return const pointers. Use const_ptr_if(ossl400) in the FFI bindings and cast to *mut at the call sites since we only return immutable references. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * Add Version::Openssl4xx, bind SSL_OP_IGNORE_UNEXPECTED_EOF Add a distinct Openssl4xx variant to the Version enum and use it for OpenSSL 4.x detection. Bind SSL_OP_IGNORE_UNEXPECTED_EOF (gated on ossl400) and set it in the default_verify_paths test to handle peers that close without close_notify. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * Add 4.0.0-beta1 in CI * cargo fmt * update a comment and some cfg guards * missed a comment * 4.0.0 --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 5f4094c commit 1fc51ef

10 files changed

Lines changed: 51 additions & 21 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ jobs:
182182
version: 338f44af3c92ef665bf740a8127a2d69c872b52a
183183
- name: openssl
184184
version: vendored
185+
- name: openssl
186+
version: 4.0.0
185187
- name: openssl
186188
version: 3.6.0
187189
- name: openssl

openssl-sys/build/cfgs.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ pub fn get(openssl_version: Option<u64>, libressl_version: Option<u64>) -> Vec<&
9393
if openssl_version >= 0x3_05_00_00_0 {
9494
cfgs.push("ossl350");
9595
}
96+
if openssl_version >= 0x4_00_00_00_0 {
97+
cfgs.push("ossl400");
98+
}
9699
}
97100

98101
cfgs

openssl-sys/build/main.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod run_bindgen;
1919

2020
#[derive(PartialEq)]
2121
enum Version {
22+
Openssl4xx,
2223
Openssl3xx,
2324
Openssl11x,
2425
Libressl,
@@ -180,6 +181,7 @@ fn main() {
180181
println!("cargo:rustc-check-cfg=cfg(ossl320)");
181182
println!("cargo:rustc-check-cfg=cfg(ossl330)");
182183
println!("cargo:rustc-check-cfg=cfg(ossl340)");
184+
println!("cargo:rustc-check-cfg=cfg(ossl400)");
183185

184186
check_ssl_kind();
185187

@@ -226,7 +228,9 @@ fn main() {
226228
}
227229
}
228230
None => match version {
229-
Version::Openssl3xx | Version::Openssl11x if target.contains("windows-msvc") => {
231+
Version::Openssl4xx | Version::Openssl3xx | Version::Openssl11x
232+
if target.contains("windows-msvc") =>
233+
{
230234
vec!["libssl", "libcrypto"]
231235
}
232236
_ => vec!["ssl", "crypto"],
@@ -270,7 +274,7 @@ fn main() {
270274
}
271275

272276
// https://github.com/openssl/openssl/pull/15086
273-
if version == Version::Openssl3xx
277+
if (version == Version::Openssl3xx || version == Version::Openssl4xx)
274278
&& kind == "static"
275279
&& (env::var("CARGO_CFG_TARGET_OS").unwrap() == "linux"
276280
|| env::var("CARGO_CFG_TARGET_OS").unwrap() == "android")
@@ -436,8 +440,10 @@ See rust-openssl documentation for more information:
436440
let openssl_version = openssl_version.unwrap();
437441
println!("cargo:version_number={openssl_version:x}");
438442

439-
if openssl_version >= 0x4_00_00_00_0 {
443+
if openssl_version >= 0x5_00_00_00_0 {
440444
version_error()
445+
} else if openssl_version >= 0x4_00_00_00_0 {
446+
Version::Openssl4xx
441447
} else if openssl_version >= 0x3_00_00_00_0 {
442448
Version::Openssl3xx
443449
} else if openssl_version >= 0x1_01_01_00_0 {
@@ -460,7 +466,7 @@ fn version_error() -> ! {
460466
panic!(
461467
"
462468
463-
This crate is only compatible with OpenSSL (version 1.1.0, 1.1.1, or 3.x), or LibreSSL 3.5.0
469+
This crate is only compatible with OpenSSL (version 1.1.0, 1.1.1, 3.x, or 4.x), or LibreSSL 3.5.0
464470
through 4.2.x, but a different version of OpenSSL was found. The build is now aborting
465471
due to this version mismatch.
466472

openssl-sys/src/handwritten/x509.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,13 @@ extern "C" {
332332
pub fn X509_CRL_get_REVOKED(crl: *mut X509_CRL) -> *mut stack_st_X509_REVOKED;
333333
pub fn X509_CRL_get0_nextUpdate(x: *const X509_CRL) -> *const ASN1_TIME;
334334
pub fn X509_CRL_get0_lastUpdate(x: *const X509_CRL) -> *const ASN1_TIME;
335-
pub fn X509_CRL_get_issuer(x: *const X509_CRL) -> *mut X509_NAME;
335+
}
336+
const_ptr_api! {
337+
extern "C" {
338+
pub fn X509_CRL_get_issuer(x: *const X509_CRL) -> #[const_ptr_if(ossl400)] X509_NAME;
339+
}
340+
}
341+
extern "C" {
336342

337343
#[cfg(ossl110)]
338344
pub fn X509_get0_extensions(req: *const X509) -> *const stack_st_X509_EXTENSION;
@@ -370,8 +376,8 @@ const_ptr_api! {
370376
set: c_int,
371377
) -> c_int;
372378
pub fn i2d_X509_NAME(n: #[const_ptr_if(ossl300)] X509_NAME, buf: *mut *mut u8) -> c_int;
373-
pub fn X509_NAME_ENTRY_get_object(ne: *const X509_NAME_ENTRY) -> *mut ASN1_OBJECT;
374-
pub fn X509_NAME_ENTRY_get_data(ne: *const X509_NAME_ENTRY) -> *mut ASN1_STRING;
379+
pub fn X509_NAME_ENTRY_get_object(ne: *const X509_NAME_ENTRY) -> #[const_ptr_if(ossl400)] ASN1_OBJECT;
380+
pub fn X509_NAME_ENTRY_get_data(ne: *const X509_NAME_ENTRY) -> #[const_ptr_if(ossl400)] ASN1_STRING;
375381
}
376382
}
377383
extern "C" {

openssl-sys/src/ssl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ cfg_if! {
8282
}
8383
#[cfg(ossl110)]
8484
pub const SSL_OP_SAFARI_ECDHE_ECDSA_BUG: ssl_op_type!() = 0x00000040;
85+
#[cfg(ossl300)]
86+
pub const SSL_OP_IGNORE_UNEXPECTED_EOF: ssl_op_type!() = 0x00000080;
8587

8688
pub const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: ssl_op_type!() = 0x00000800;
8789

openssl/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ fn main() {
5050
println!("cargo:rustc-check-cfg=cfg(ossl330)");
5151
println!("cargo:rustc-check-cfg=cfg(ossl340)");
5252
println!("cargo:rustc-check-cfg=cfg(ossl350)");
53+
println!("cargo:rustc-check-cfg=cfg(ossl400)");
5354

5455
if env::var("DEP_OPENSSL_LIBRESSL").is_ok() {
5556
println!("cargo:rustc-cfg=libressl");
@@ -155,5 +156,8 @@ fn main() {
155156
if version >= 0x3_05_00_00_0 {
156157
println!("cargo:rustc-cfg=ossl350");
157158
}
159+
if version >= 0x4_00_00_00_0 {
160+
println!("cargo:rustc-cfg=ossl400");
161+
}
158162
}
159163
}

openssl/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Bindings to OpenSSL
22
//!
33
//! This crate provides a safe interface to the popular OpenSSL cryptography library. OpenSSL versions 1.0.2 through
4-
//! 3.x.x and LibreSSL versions 3.5 through 4.2.x are supported.
4+
//! 4.x.x and LibreSSL versions 3.5 through 4.2.x are supported.
55
//!
66
//! # Building
77
//!

openssl/src/ssl/mod.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ bitflags! {
150150
/// Disables a countermeasure against an SSLv3/TLSv1.0 vulnerability affecting CBC ciphers.
151151
const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
152152

153+
/// If set, a peer closing the connection without sending a close_notify alert is
154+
/// treated as a normal EOF rather than an error.
155+
#[cfg(ossl300)]
156+
const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
157+
153158
/// A "reasonable default" set of options which enables compatibility flags.
154159
#[cfg(not(any(boringssl, awslc)))]
155160
const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
@@ -3731,6 +3736,10 @@ impl<S: Read + Write> SslStream<S> {
37313736
/// then the first `n` bytes of `buf` are guaranteed to be initialized.
37323737
#[corresponds(SSL_read_ex)]
37333738
pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3739+
if buf.is_empty() {
3740+
return Ok(0);
3741+
}
3742+
37343743
cfg_if! {
37353744
if #[cfg(any(ossl111, libressl))] {
37363745
let mut readbytes = 0;
@@ -3749,10 +3758,6 @@ impl<S: Read + Write> SslStream<S> {
37493758
Err(self.make_error(ret))
37503759
}
37513760
} else {
3752-
if buf.is_empty() {
3753-
return Ok(0);
3754-
}
3755-
37563761
let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
37573762
let ret = unsafe {
37583763
ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
@@ -3772,6 +3777,10 @@ impl<S: Read + Write> SslStream<S> {
37723777
/// OpenSSL is waiting on read or write readiness.
37733778
#[corresponds(SSL_write_ex)]
37743779
pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3780+
if buf.is_empty() {
3781+
return Ok(0);
3782+
}
3783+
37753784
cfg_if! {
37763785
if #[cfg(any(ossl111, libressl))] {
37773786
let mut written = 0;
@@ -3790,10 +3799,6 @@ impl<S: Read + Write> SslStream<S> {
37903799
Err(self.make_error(ret))
37913800
}
37923801
} else {
3793-
if buf.is_empty() {
3794-
return Ok(0);
3795-
}
3796-
37973802
let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
37983803
let ret = unsafe {
37993804
ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)

openssl/src/ssl/test/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,8 @@ fn default_verify_paths() {
675675
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
676676
ctx.set_default_verify_paths().unwrap();
677677
ctx.set_verify(SslVerifyMode::PEER);
678+
#[cfg(ossl400)]
679+
ctx.set_options(super::SslOptions::IGNORE_UNEXPECTED_EOF);
678680
let ctx = ctx.build();
679681
let s = match TcpStream::connect("google.com:443") {
680682
Ok(s) => s,
@@ -965,7 +967,7 @@ fn cert_store() {
965967
}
966968

967969
#[test]
968-
#[cfg_attr(any(boringssl, awslc), ignore)]
970+
#[cfg_attr(any(boringssl, awslc, ossl400), ignore)]
969971
fn tmp_dh_callback() {
970972
static CALLED_BACK: AtomicBool = AtomicBool::new(false);
971973

@@ -989,7 +991,7 @@ fn tmp_dh_callback() {
989991
}
990992

991993
#[test]
992-
#[cfg_attr(any(boringssl, awslc), ignore)]
994+
#[cfg_attr(any(boringssl, awslc, ossl400), ignore)]
993995
fn tmp_dh_callback_ssl() {
994996
static CALLED_BACK: AtomicBool = AtomicBool::new(false);
995997

openssl/src/x509/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ impl X509NameEntryRef {
13241324
pub fn data(&self) -> &Asn1StringRef {
13251325
unsafe {
13261326
let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr());
1327-
Asn1StringRef::from_ptr(data)
1327+
Asn1StringRef::from_ptr(data as *mut _)
13281328
}
13291329
}
13301330

@@ -1334,7 +1334,7 @@ impl X509NameEntryRef {
13341334
pub fn object(&self) -> &Asn1ObjectRef {
13351335
unsafe {
13361336
let object = ffi::X509_NAME_ENTRY_get_object(self.as_ptr());
1337-
Asn1ObjectRef::from_ptr(object)
1337+
Asn1ObjectRef::from_ptr(object as *mut _)
13381338
}
13391339
}
13401340
}
@@ -1873,7 +1873,7 @@ impl X509CrlRef {
18731873
unsafe {
18741874
let name = X509_CRL_get_issuer(self.as_ptr());
18751875
assert!(!name.is_null());
1876-
X509NameRef::from_ptr(name)
1876+
X509NameRef::from_ptr(name as *mut _)
18771877
}
18781878
}
18791879

0 commit comments

Comments
 (0)