From fddd1cecea0cf3688fc80b7aa5d30f6f0733ead2 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 31 Jan 2022 11:06:06 +0100 Subject: [PATCH 1/2] Don't return shutdown errors during shutdown --- boring/src/ssl/mod.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/boring/src/ssl/mod.rs b/boring/src/ssl/mod.rs index 19688c396..435b54464 100644 --- a/boring/src/ssl/mod.rs +++ b/boring/src/ssl/mod.rs @@ -4069,7 +4069,24 @@ impl SslStream { match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } { 0 => Ok(ShutdownResult::Sent), 1 => Ok(ShutdownResult::Received), - n => Err(self.make_error(n)), + n => { + let e = self.make_error(n); + + // If boring returns PROTOCOL_IS_SHUTDOWN then the connection + // has already been shutdown and we can just return Ok(()), as + // this was exactly what we wanted to do anyway. + if e.code() == ErrorCode::SSL { + if let Some(stack) = e.ssl_error() { + if let Some(first) = stack.errors().first() { + if first.code() as i32 == boring_sys::SSL_R_PROTOCOL_IS_SHUTDOWN { + return Ok(ShutdownResult::Received); + } + } + } + } + + Err(e) + } } } From cd2909abcd8c054ad428e028a5078d0170a8d765 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 13 Jun 2025 13:56:14 +0100 Subject: [PATCH 2/2] Peek error --- boring/src/error.rs | 19 ++++++++++++++++++- boring/src/ssl/mod.rs | 4 +++- boring/src/x509/mod.rs | 9 ++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/boring/src/error.rs b/boring/src/error.rs index 1e8f79467..4c4a451ca 100644 --- a/boring/src/error.rs +++ b/boring/src/error.rs @@ -152,7 +152,19 @@ impl Error { /// Pops the first error off the OpenSSL error stack. #[must_use = "Use ErrorStack::clear() to drop the error stack"] #[corresponds(ERR_get_error_line_data)] + #[inline] pub fn get() -> Option { + Self::get_(false) + } + + /// Use [`ErrorStack::clear()`] or [`ErrorStack::get()`] afterwards + #[corresponds(ERR_peek_last_error_line_data)] + #[inline] + pub fn peek() -> Option { + Self::get_(true) + } + + fn get_(peek: bool) -> Option { unsafe { ffi::init(); @@ -160,7 +172,12 @@ impl Error { let mut line = 0; let mut data = ptr::null(); let mut flags = 0; - match ffi::ERR_get_error_line_data(&mut file, &mut line, &mut data, &mut flags) { + let code = if !peek { + ffi::ERR_get_error_line_data(&mut file, &mut line, &mut data, &mut flags) + } else { + ffi::ERR_peek_last_error_line_data(&mut file, &mut line, &mut data, &mut flags) + }; + match code { 0 => None, code => { // The memory referenced by data is only valid until that slot is overwritten diff --git a/boring/src/ssl/mod.rs b/boring/src/ssl/mod.rs index 435b54464..c54ae763b 100644 --- a/boring/src/ssl/mod.rs +++ b/boring/src/ssl/mod.rs @@ -4078,7 +4078,9 @@ impl SslStream { if e.code() == ErrorCode::SSL { if let Some(stack) = e.ssl_error() { if let Some(first) = stack.errors().first() { - if first.code() as i32 == boring_sys::SSL_R_PROTOCOL_IS_SHUTDOWN { + if first.library_reason(ffi::ERR_LIB_SSL) + == Some(ffi::SSL_R_PROTOCOL_IS_SHUTDOWN) + { return Ok(ShutdownResult::Received); } } diff --git a/boring/src/x509/mod.rs b/boring/src/x509/mod.rs index cd5d428e8..a3820c224 100644 --- a/boring/src/x509/mod.rs +++ b/boring/src/x509/mod.rs @@ -28,7 +28,7 @@ use crate::asn1::{ }; use crate::bio::{MemBio, MemBioSlice}; use crate::conf::ConfRef; -use crate::error::ErrorStack; +use crate::error::{Error as PackedError, ErrorStack}; use crate::ex_data::Index; use crate::hash::{DigestBytes, MessageDigest}; use crate::nid::Nid; @@ -809,10 +809,9 @@ impl X509 { let r = ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut()); if r.is_null() { - let err = ffi::ERR_peek_last_error(); - - if ffi::ERR_GET_LIB(err) == ffi::ERR_LIB_PEM.0.try_into().unwrap() - && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE + if PackedError::peek() + .and_then(|err| err.library_reason(ffi::ERR_LIB_PEM)) + .is_some_and(|code| code == ffi::PEM_R_NO_START_LINE) { ErrorStack::clear(); break;