192f3ab15Sopenharmony_ci//! Errors returned by OpenSSL library. 292f3ab15Sopenharmony_ci//! 392f3ab15Sopenharmony_ci//! OpenSSL errors are stored in an `ErrorStack`. Most methods in the crate 492f3ab15Sopenharmony_ci//! returns a `Result<T, ErrorStack>` type. 592f3ab15Sopenharmony_ci//! 692f3ab15Sopenharmony_ci//! # Examples 792f3ab15Sopenharmony_ci//! 892f3ab15Sopenharmony_ci//! ``` 992f3ab15Sopenharmony_ci//! use openssl::error::ErrorStack; 1092f3ab15Sopenharmony_ci//! use openssl::bn::BigNum; 1192f3ab15Sopenharmony_ci//! 1292f3ab15Sopenharmony_ci//! let an_error = BigNum::from_dec_str("Cannot parse letters"); 1392f3ab15Sopenharmony_ci//! match an_error { 1492f3ab15Sopenharmony_ci//! Ok(_) => (), 1592f3ab15Sopenharmony_ci//! Err(e) => println!("Parsing Error: {:?}", e), 1692f3ab15Sopenharmony_ci//! } 1792f3ab15Sopenharmony_ci//! ``` 1892f3ab15Sopenharmony_ciuse cfg_if::cfg_if; 1992f3ab15Sopenharmony_ciuse libc::{c_char, c_int}; 2092f3ab15Sopenharmony_ciuse std::borrow::Cow; 2192f3ab15Sopenharmony_ci#[cfg(boringssl)] 2292f3ab15Sopenharmony_ciuse std::convert::TryInto; 2392f3ab15Sopenharmony_ciuse std::error; 2492f3ab15Sopenharmony_ciuse std::ffi::CStr; 2592f3ab15Sopenharmony_ciuse std::fmt; 2692f3ab15Sopenharmony_ciuse std::io; 2792f3ab15Sopenharmony_ciuse std::ptr; 2892f3ab15Sopenharmony_ciuse std::str; 2992f3ab15Sopenharmony_ci 3092f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 3192f3ab15Sopenharmony_citype ErrType = libc::c_ulong; 3292f3ab15Sopenharmony_ci#[cfg(boringssl)] 3392f3ab15Sopenharmony_citype ErrType = libc::c_uint; 3492f3ab15Sopenharmony_ci 3592f3ab15Sopenharmony_ci/// Collection of [`Error`]s from OpenSSL. 3692f3ab15Sopenharmony_ci/// 3792f3ab15Sopenharmony_ci/// [`Error`]: struct.Error.html 3892f3ab15Sopenharmony_ci#[derive(Debug, Clone)] 3992f3ab15Sopenharmony_cipub struct ErrorStack(Vec<Error>); 4092f3ab15Sopenharmony_ci 4192f3ab15Sopenharmony_ciimpl ErrorStack { 4292f3ab15Sopenharmony_ci /// Returns the contents of the OpenSSL error stack. 4392f3ab15Sopenharmony_ci pub fn get() -> ErrorStack { 4492f3ab15Sopenharmony_ci let mut vec = vec![]; 4592f3ab15Sopenharmony_ci while let Some(err) = Error::get() { 4692f3ab15Sopenharmony_ci vec.push(err); 4792f3ab15Sopenharmony_ci } 4892f3ab15Sopenharmony_ci ErrorStack(vec) 4992f3ab15Sopenharmony_ci } 5092f3ab15Sopenharmony_ci 5192f3ab15Sopenharmony_ci /// Pushes the errors back onto the OpenSSL error stack. 5292f3ab15Sopenharmony_ci pub fn put(&self) { 5392f3ab15Sopenharmony_ci for error in self.errors() { 5492f3ab15Sopenharmony_ci error.put(); 5592f3ab15Sopenharmony_ci } 5692f3ab15Sopenharmony_ci } 5792f3ab15Sopenharmony_ci} 5892f3ab15Sopenharmony_ci 5992f3ab15Sopenharmony_ciimpl ErrorStack { 6092f3ab15Sopenharmony_ci /// Returns the errors in the stack. 6192f3ab15Sopenharmony_ci pub fn errors(&self) -> &[Error] { 6292f3ab15Sopenharmony_ci &self.0 6392f3ab15Sopenharmony_ci } 6492f3ab15Sopenharmony_ci} 6592f3ab15Sopenharmony_ci 6692f3ab15Sopenharmony_ciimpl fmt::Display for ErrorStack { 6792f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 6892f3ab15Sopenharmony_ci if self.0.is_empty() { 6992f3ab15Sopenharmony_ci return fmt.write_str("OpenSSL error"); 7092f3ab15Sopenharmony_ci } 7192f3ab15Sopenharmony_ci 7292f3ab15Sopenharmony_ci let mut first = true; 7392f3ab15Sopenharmony_ci for err in &self.0 { 7492f3ab15Sopenharmony_ci if !first { 7592f3ab15Sopenharmony_ci fmt.write_str(", ")?; 7692f3ab15Sopenharmony_ci } 7792f3ab15Sopenharmony_ci write!(fmt, "{}", err)?; 7892f3ab15Sopenharmony_ci first = false; 7992f3ab15Sopenharmony_ci } 8092f3ab15Sopenharmony_ci Ok(()) 8192f3ab15Sopenharmony_ci } 8292f3ab15Sopenharmony_ci} 8392f3ab15Sopenharmony_ci 8492f3ab15Sopenharmony_ciimpl error::Error for ErrorStack {} 8592f3ab15Sopenharmony_ci 8692f3ab15Sopenharmony_ciimpl From<ErrorStack> for io::Error { 8792f3ab15Sopenharmony_ci fn from(e: ErrorStack) -> io::Error { 8892f3ab15Sopenharmony_ci io::Error::new(io::ErrorKind::Other, e) 8992f3ab15Sopenharmony_ci } 9092f3ab15Sopenharmony_ci} 9192f3ab15Sopenharmony_ci 9292f3ab15Sopenharmony_ciimpl From<ErrorStack> for fmt::Error { 9392f3ab15Sopenharmony_ci fn from(_: ErrorStack) -> fmt::Error { 9492f3ab15Sopenharmony_ci fmt::Error 9592f3ab15Sopenharmony_ci } 9692f3ab15Sopenharmony_ci} 9792f3ab15Sopenharmony_ci 9892f3ab15Sopenharmony_ci/// An error reported from OpenSSL. 9992f3ab15Sopenharmony_ci#[derive(Clone)] 10092f3ab15Sopenharmony_cipub struct Error { 10192f3ab15Sopenharmony_ci code: ErrType, 10292f3ab15Sopenharmony_ci file: ShimStr, 10392f3ab15Sopenharmony_ci line: c_int, 10492f3ab15Sopenharmony_ci func: Option<ShimStr>, 10592f3ab15Sopenharmony_ci data: Option<Cow<'static, str>>, 10692f3ab15Sopenharmony_ci} 10792f3ab15Sopenharmony_ci 10892f3ab15Sopenharmony_ciunsafe impl Sync for Error {} 10992f3ab15Sopenharmony_ciunsafe impl Send for Error {} 11092f3ab15Sopenharmony_ci 11192f3ab15Sopenharmony_ciimpl Error { 11292f3ab15Sopenharmony_ci /// Returns the first error on the OpenSSL error stack. 11392f3ab15Sopenharmony_ci pub fn get() -> Option<Error> { 11492f3ab15Sopenharmony_ci unsafe { 11592f3ab15Sopenharmony_ci ffi::init(); 11692f3ab15Sopenharmony_ci 11792f3ab15Sopenharmony_ci let mut file = ptr::null(); 11892f3ab15Sopenharmony_ci let mut line = 0; 11992f3ab15Sopenharmony_ci let mut func = ptr::null(); 12092f3ab15Sopenharmony_ci let mut data = ptr::null(); 12192f3ab15Sopenharmony_ci let mut flags = 0; 12292f3ab15Sopenharmony_ci match ERR_get_error_all(&mut file, &mut line, &mut func, &mut data, &mut flags) { 12392f3ab15Sopenharmony_ci 0 => None, 12492f3ab15Sopenharmony_ci code => { 12592f3ab15Sopenharmony_ci // The memory referenced by data is only valid until that slot is overwritten 12692f3ab15Sopenharmony_ci // in the error stack, so we'll need to copy it off if it's dynamic 12792f3ab15Sopenharmony_ci let data = if flags & ffi::ERR_TXT_STRING != 0 { 12892f3ab15Sopenharmony_ci let bytes = CStr::from_ptr(data as *const _).to_bytes(); 12992f3ab15Sopenharmony_ci let data = str::from_utf8(bytes).unwrap(); 13092f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 13192f3ab15Sopenharmony_ci let data = if flags & ffi::ERR_TXT_MALLOCED != 0 { 13292f3ab15Sopenharmony_ci Cow::Owned(data.to_string()) 13392f3ab15Sopenharmony_ci } else { 13492f3ab15Sopenharmony_ci Cow::Borrowed(data) 13592f3ab15Sopenharmony_ci }; 13692f3ab15Sopenharmony_ci #[cfg(boringssl)] 13792f3ab15Sopenharmony_ci let data = Cow::Borrowed(data); 13892f3ab15Sopenharmony_ci Some(data) 13992f3ab15Sopenharmony_ci } else { 14092f3ab15Sopenharmony_ci None 14192f3ab15Sopenharmony_ci }; 14292f3ab15Sopenharmony_ci 14392f3ab15Sopenharmony_ci let file = ShimStr::new(file); 14492f3ab15Sopenharmony_ci 14592f3ab15Sopenharmony_ci let func = if func.is_null() { 14692f3ab15Sopenharmony_ci None 14792f3ab15Sopenharmony_ci } else { 14892f3ab15Sopenharmony_ci Some(ShimStr::new(func)) 14992f3ab15Sopenharmony_ci }; 15092f3ab15Sopenharmony_ci 15192f3ab15Sopenharmony_ci Some(Error { 15292f3ab15Sopenharmony_ci code, 15392f3ab15Sopenharmony_ci file, 15492f3ab15Sopenharmony_ci line, 15592f3ab15Sopenharmony_ci func, 15692f3ab15Sopenharmony_ci data, 15792f3ab15Sopenharmony_ci }) 15892f3ab15Sopenharmony_ci } 15992f3ab15Sopenharmony_ci } 16092f3ab15Sopenharmony_ci } 16192f3ab15Sopenharmony_ci } 16292f3ab15Sopenharmony_ci 16392f3ab15Sopenharmony_ci /// Pushes the error back onto the OpenSSL error stack. 16492f3ab15Sopenharmony_ci pub fn put(&self) { 16592f3ab15Sopenharmony_ci self.put_error(); 16692f3ab15Sopenharmony_ci 16792f3ab15Sopenharmony_ci unsafe { 16892f3ab15Sopenharmony_ci let data = match self.data { 16992f3ab15Sopenharmony_ci Some(Cow::Borrowed(data)) => Some((data.as_ptr() as *mut c_char, 0)), 17092f3ab15Sopenharmony_ci Some(Cow::Owned(ref data)) => { 17192f3ab15Sopenharmony_ci let ptr = ffi::CRYPTO_malloc( 17292f3ab15Sopenharmony_ci (data.len() + 1) as _, 17392f3ab15Sopenharmony_ci concat!(file!(), "\0").as_ptr() as _, 17492f3ab15Sopenharmony_ci line!() as _, 17592f3ab15Sopenharmony_ci ) as *mut c_char; 17692f3ab15Sopenharmony_ci if ptr.is_null() { 17792f3ab15Sopenharmony_ci None 17892f3ab15Sopenharmony_ci } else { 17992f3ab15Sopenharmony_ci ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len()); 18092f3ab15Sopenharmony_ci *ptr.add(data.len()) = 0; 18192f3ab15Sopenharmony_ci Some((ptr, ffi::ERR_TXT_MALLOCED)) 18292f3ab15Sopenharmony_ci } 18392f3ab15Sopenharmony_ci } 18492f3ab15Sopenharmony_ci None => None, 18592f3ab15Sopenharmony_ci }; 18692f3ab15Sopenharmony_ci if let Some((ptr, flags)) = data { 18792f3ab15Sopenharmony_ci ffi::ERR_set_error_data(ptr, flags | ffi::ERR_TXT_STRING); 18892f3ab15Sopenharmony_ci } 18992f3ab15Sopenharmony_ci } 19092f3ab15Sopenharmony_ci } 19192f3ab15Sopenharmony_ci 19292f3ab15Sopenharmony_ci #[cfg(ossl300)] 19392f3ab15Sopenharmony_ci fn put_error(&self) { 19492f3ab15Sopenharmony_ci unsafe { 19592f3ab15Sopenharmony_ci ffi::ERR_new(); 19692f3ab15Sopenharmony_ci ffi::ERR_set_debug( 19792f3ab15Sopenharmony_ci self.file.as_ptr(), 19892f3ab15Sopenharmony_ci self.line, 19992f3ab15Sopenharmony_ci self.func.as_ref().map_or(ptr::null(), |s| s.as_ptr()), 20092f3ab15Sopenharmony_ci ); 20192f3ab15Sopenharmony_ci ffi::ERR_set_error(self.library_code(), self.reason_code(), ptr::null()); 20292f3ab15Sopenharmony_ci } 20392f3ab15Sopenharmony_ci } 20492f3ab15Sopenharmony_ci 20592f3ab15Sopenharmony_ci #[cfg(not(ossl300))] 20692f3ab15Sopenharmony_ci fn put_error(&self) { 20792f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 20892f3ab15Sopenharmony_ci let line = self.line; 20992f3ab15Sopenharmony_ci #[cfg(boringssl)] 21092f3ab15Sopenharmony_ci let line = self.line.try_into().unwrap(); 21192f3ab15Sopenharmony_ci unsafe { 21292f3ab15Sopenharmony_ci ffi::ERR_put_error( 21392f3ab15Sopenharmony_ci self.library_code(), 21492f3ab15Sopenharmony_ci ffi::ERR_GET_FUNC(self.code), 21592f3ab15Sopenharmony_ci self.reason_code(), 21692f3ab15Sopenharmony_ci self.file.as_ptr(), 21792f3ab15Sopenharmony_ci line, 21892f3ab15Sopenharmony_ci ); 21992f3ab15Sopenharmony_ci } 22092f3ab15Sopenharmony_ci } 22192f3ab15Sopenharmony_ci 22292f3ab15Sopenharmony_ci /// Returns the raw OpenSSL error code for this error. 22392f3ab15Sopenharmony_ci pub fn code(&self) -> ErrType { 22492f3ab15Sopenharmony_ci self.code 22592f3ab15Sopenharmony_ci } 22692f3ab15Sopenharmony_ci 22792f3ab15Sopenharmony_ci /// Returns the name of the library reporting the error, if available. 22892f3ab15Sopenharmony_ci pub fn library(&self) -> Option<&'static str> { 22992f3ab15Sopenharmony_ci unsafe { 23092f3ab15Sopenharmony_ci let cstr = ffi::ERR_lib_error_string(self.code); 23192f3ab15Sopenharmony_ci if cstr.is_null() { 23292f3ab15Sopenharmony_ci return None; 23392f3ab15Sopenharmony_ci } 23492f3ab15Sopenharmony_ci let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); 23592f3ab15Sopenharmony_ci Some(str::from_utf8(bytes).unwrap()) 23692f3ab15Sopenharmony_ci } 23792f3ab15Sopenharmony_ci } 23892f3ab15Sopenharmony_ci 23992f3ab15Sopenharmony_ci /// Returns the raw OpenSSL error constant for the library reporting the 24092f3ab15Sopenharmony_ci /// error. 24192f3ab15Sopenharmony_ci // On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on 24292f3ab15Sopenharmony_ci // OpenSSL/LibreSSL they're safe. 24392f3ab15Sopenharmony_ci #[allow(unused_unsafe)] 24492f3ab15Sopenharmony_ci pub fn library_code(&self) -> libc::c_int { 24592f3ab15Sopenharmony_ci unsafe { ffi::ERR_GET_LIB(self.code) } 24692f3ab15Sopenharmony_ci } 24792f3ab15Sopenharmony_ci 24892f3ab15Sopenharmony_ci /// Returns the name of the function reporting the error. 24992f3ab15Sopenharmony_ci pub fn function(&self) -> Option<RetStr<'_>> { 25092f3ab15Sopenharmony_ci self.func.as_ref().map(|s| s.as_str()) 25192f3ab15Sopenharmony_ci } 25292f3ab15Sopenharmony_ci 25392f3ab15Sopenharmony_ci /// Returns the reason for the error. 25492f3ab15Sopenharmony_ci pub fn reason(&self) -> Option<&'static str> { 25592f3ab15Sopenharmony_ci unsafe { 25692f3ab15Sopenharmony_ci let cstr = ffi::ERR_reason_error_string(self.code); 25792f3ab15Sopenharmony_ci if cstr.is_null() { 25892f3ab15Sopenharmony_ci return None; 25992f3ab15Sopenharmony_ci } 26092f3ab15Sopenharmony_ci let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); 26192f3ab15Sopenharmony_ci Some(str::from_utf8(bytes).unwrap()) 26292f3ab15Sopenharmony_ci } 26392f3ab15Sopenharmony_ci } 26492f3ab15Sopenharmony_ci 26592f3ab15Sopenharmony_ci /// Returns the raw OpenSSL error constant for the reason for the error. 26692f3ab15Sopenharmony_ci // On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on 26792f3ab15Sopenharmony_ci // OpenSSL/LibreSSL they're safe. 26892f3ab15Sopenharmony_ci #[allow(unused_unsafe)] 26992f3ab15Sopenharmony_ci pub fn reason_code(&self) -> libc::c_int { 27092f3ab15Sopenharmony_ci unsafe { ffi::ERR_GET_REASON(self.code) } 27192f3ab15Sopenharmony_ci } 27292f3ab15Sopenharmony_ci 27392f3ab15Sopenharmony_ci /// Returns the name of the source file which encountered the error. 27492f3ab15Sopenharmony_ci pub fn file(&self) -> RetStr<'_> { 27592f3ab15Sopenharmony_ci self.file.as_str() 27692f3ab15Sopenharmony_ci } 27792f3ab15Sopenharmony_ci 27892f3ab15Sopenharmony_ci /// Returns the line in the source file which encountered the error. 27992f3ab15Sopenharmony_ci pub fn line(&self) -> u32 { 28092f3ab15Sopenharmony_ci self.line as u32 28192f3ab15Sopenharmony_ci } 28292f3ab15Sopenharmony_ci 28392f3ab15Sopenharmony_ci /// Returns additional data describing the error. 28492f3ab15Sopenharmony_ci #[allow(clippy::option_as_ref_deref)] 28592f3ab15Sopenharmony_ci pub fn data(&self) -> Option<&str> { 28692f3ab15Sopenharmony_ci self.data.as_ref().map(|s| &**s) 28792f3ab15Sopenharmony_ci } 28892f3ab15Sopenharmony_ci} 28992f3ab15Sopenharmony_ci 29092f3ab15Sopenharmony_ciimpl fmt::Debug for Error { 29192f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 29292f3ab15Sopenharmony_ci let mut builder = fmt.debug_struct("Error"); 29392f3ab15Sopenharmony_ci builder.field("code", &self.code()); 29492f3ab15Sopenharmony_ci if let Some(library) = self.library() { 29592f3ab15Sopenharmony_ci builder.field("library", &library); 29692f3ab15Sopenharmony_ci } 29792f3ab15Sopenharmony_ci if let Some(function) = self.function() { 29892f3ab15Sopenharmony_ci builder.field("function", &function); 29992f3ab15Sopenharmony_ci } 30092f3ab15Sopenharmony_ci if let Some(reason) = self.reason() { 30192f3ab15Sopenharmony_ci builder.field("reason", &reason); 30292f3ab15Sopenharmony_ci } 30392f3ab15Sopenharmony_ci builder.field("file", &self.file()); 30492f3ab15Sopenharmony_ci builder.field("line", &self.line()); 30592f3ab15Sopenharmony_ci if let Some(data) = self.data() { 30692f3ab15Sopenharmony_ci builder.field("data", &data); 30792f3ab15Sopenharmony_ci } 30892f3ab15Sopenharmony_ci builder.finish() 30992f3ab15Sopenharmony_ci } 31092f3ab15Sopenharmony_ci} 31192f3ab15Sopenharmony_ci 31292f3ab15Sopenharmony_ciimpl fmt::Display for Error { 31392f3ab15Sopenharmony_ci // On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on 31492f3ab15Sopenharmony_ci // OpenSSL/LibreSSL they're safe. 31592f3ab15Sopenharmony_ci #[allow(unused_unsafe)] 31692f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 31792f3ab15Sopenharmony_ci write!(fmt, "error:{:08X}", self.code())?; 31892f3ab15Sopenharmony_ci match self.library() { 31992f3ab15Sopenharmony_ci Some(l) => write!(fmt, ":{}", l)?, 32092f3ab15Sopenharmony_ci None => write!(fmt, ":lib({})", self.library_code())?, 32192f3ab15Sopenharmony_ci } 32292f3ab15Sopenharmony_ci match self.function() { 32392f3ab15Sopenharmony_ci Some(f) => write!(fmt, ":{}", f)?, 32492f3ab15Sopenharmony_ci None => write!(fmt, ":func({})", unsafe { ffi::ERR_GET_FUNC(self.code()) })?, 32592f3ab15Sopenharmony_ci } 32692f3ab15Sopenharmony_ci match self.reason() { 32792f3ab15Sopenharmony_ci Some(r) => write!(fmt, ":{}", r)?, 32892f3ab15Sopenharmony_ci None => write!(fmt, ":reason({})", self.reason_code())?, 32992f3ab15Sopenharmony_ci } 33092f3ab15Sopenharmony_ci write!( 33192f3ab15Sopenharmony_ci fmt, 33292f3ab15Sopenharmony_ci ":{}:{}:{}", 33392f3ab15Sopenharmony_ci self.file(), 33492f3ab15Sopenharmony_ci self.line(), 33592f3ab15Sopenharmony_ci self.data().unwrap_or("") 33692f3ab15Sopenharmony_ci ) 33792f3ab15Sopenharmony_ci } 33892f3ab15Sopenharmony_ci} 33992f3ab15Sopenharmony_ci 34092f3ab15Sopenharmony_ciimpl error::Error for Error {} 34192f3ab15Sopenharmony_ci 34292f3ab15Sopenharmony_cicfg_if! { 34392f3ab15Sopenharmony_ci if #[cfg(ossl300)] { 34492f3ab15Sopenharmony_ci use std::ffi::{CString}; 34592f3ab15Sopenharmony_ci use ffi::ERR_get_error_all; 34692f3ab15Sopenharmony_ci 34792f3ab15Sopenharmony_ci type RetStr<'a> = &'a str; 34892f3ab15Sopenharmony_ci 34992f3ab15Sopenharmony_ci #[derive(Clone)] 35092f3ab15Sopenharmony_ci struct ShimStr(CString); 35192f3ab15Sopenharmony_ci 35292f3ab15Sopenharmony_ci impl ShimStr { 35392f3ab15Sopenharmony_ci unsafe fn new(s: *const c_char) -> Self { 35492f3ab15Sopenharmony_ci ShimStr(CStr::from_ptr(s).to_owned()) 35592f3ab15Sopenharmony_ci } 35692f3ab15Sopenharmony_ci 35792f3ab15Sopenharmony_ci fn as_ptr(&self) -> *const c_char { 35892f3ab15Sopenharmony_ci self.0.as_ptr() 35992f3ab15Sopenharmony_ci } 36092f3ab15Sopenharmony_ci 36192f3ab15Sopenharmony_ci fn as_str(&self) -> &str { 36292f3ab15Sopenharmony_ci self.0.to_str().unwrap() 36392f3ab15Sopenharmony_ci } 36492f3ab15Sopenharmony_ci } 36592f3ab15Sopenharmony_ci } else { 36692f3ab15Sopenharmony_ci #[allow(bad_style)] 36792f3ab15Sopenharmony_ci unsafe extern "C" fn ERR_get_error_all( 36892f3ab15Sopenharmony_ci file: *mut *const c_char, 36992f3ab15Sopenharmony_ci line: *mut c_int, 37092f3ab15Sopenharmony_ci func: *mut *const c_char, 37192f3ab15Sopenharmony_ci data: *mut *const c_char, 37292f3ab15Sopenharmony_ci flags: *mut c_int, 37392f3ab15Sopenharmony_ci ) -> ErrType { 37492f3ab15Sopenharmony_ci let code = ffi::ERR_get_error_line_data(file, line, data, flags); 37592f3ab15Sopenharmony_ci *func = ffi::ERR_func_error_string(code); 37692f3ab15Sopenharmony_ci code 37792f3ab15Sopenharmony_ci } 37892f3ab15Sopenharmony_ci 37992f3ab15Sopenharmony_ci type RetStr<'a> = &'static str; 38092f3ab15Sopenharmony_ci 38192f3ab15Sopenharmony_ci #[derive(Clone)] 38292f3ab15Sopenharmony_ci struct ShimStr(*const c_char); 38392f3ab15Sopenharmony_ci 38492f3ab15Sopenharmony_ci impl ShimStr { 38592f3ab15Sopenharmony_ci unsafe fn new(s: *const c_char) -> Self { 38692f3ab15Sopenharmony_ci ShimStr(s) 38792f3ab15Sopenharmony_ci } 38892f3ab15Sopenharmony_ci 38992f3ab15Sopenharmony_ci fn as_ptr(&self) -> *const c_char { 39092f3ab15Sopenharmony_ci self.0 39192f3ab15Sopenharmony_ci } 39292f3ab15Sopenharmony_ci 39392f3ab15Sopenharmony_ci fn as_str(&self) -> &'static str { 39492f3ab15Sopenharmony_ci unsafe { 39592f3ab15Sopenharmony_ci CStr::from_ptr(self.0).to_str().unwrap() 39692f3ab15Sopenharmony_ci } 39792f3ab15Sopenharmony_ci } 39892f3ab15Sopenharmony_ci } 39992f3ab15Sopenharmony_ci } 40092f3ab15Sopenharmony_ci} 40192f3ab15Sopenharmony_ci 40292f3ab15Sopenharmony_ci#[cfg(test)] 40392f3ab15Sopenharmony_cimod tests { 40492f3ab15Sopenharmony_ci #[cfg(not(ossl310))] 40592f3ab15Sopenharmony_ci use crate::nid::Nid; 40692f3ab15Sopenharmony_ci 40792f3ab15Sopenharmony_ci #[test] 40892f3ab15Sopenharmony_ci // Due to a bug in OpenSSL 3.1.0, this test can hang there. Skip for now. 40992f3ab15Sopenharmony_ci #[cfg(not(ossl310))] 41092f3ab15Sopenharmony_ci fn test_error_library_code() { 41192f3ab15Sopenharmony_ci let stack = Nid::create("not-an-oid", "invalid", "invalid").unwrap_err(); 41292f3ab15Sopenharmony_ci let errors = stack.errors(); 41392f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 41492f3ab15Sopenharmony_ci assert_eq!(errors[0].library_code(), ffi::ERR_LIB_ASN1); 41592f3ab15Sopenharmony_ci #[cfg(boringssl)] 41692f3ab15Sopenharmony_ci assert_eq!(errors[0].library_code(), ffi::ERR_LIB_OBJ as libc::c_int); 41792f3ab15Sopenharmony_ci } 41892f3ab15Sopenharmony_ci} 419