From ec65b0c67b452539fded5e06cbb6ce1d165074e0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 7 Feb 2015 21:28:54 -0800 Subject: Move docs to this repo and auto build --- openssl/src/ssl/error.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 openssl/src/ssl/error.rs (limited to 'openssl/src/ssl/error.rs') diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs new file mode 100644 index 00000000..027554c5 --- /dev/null +++ b/openssl/src/ssl/error.rs @@ -0,0 +1,122 @@ +pub use self::SslError::*; +pub use self::OpensslError::*; + +use libc::c_ulong; +use std::error; +use std::fmt; +use std::ffi::c_str_to_bytes; +use std::old_io::IoError; + +use ffi; + +/// An SSL error +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SslError { + /// The underlying stream reported an error + StreamError(IoError), + /// The SSL session has been closed by the other end + SslSessionClosed, + /// An error in the OpenSSL library + OpenSslErrors(Vec) +} + +impl fmt::Display for SslError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(error::Error::description(self)) + } +} + +impl error::Error for SslError { + fn description(&self) -> &str { + match *self { + StreamError(_) => "The underlying stream reported an error", + SslSessionClosed => "The SSL session has been closed by the other end", + OpenSslErrors(_) => "An error in the OpenSSL library", + } + } + + fn cause(&self) -> Option<&error::Error> { + match *self { + StreamError(ref err) => Some(err as &error::Error), + _ => None + } + } +} + +/// An error from the OpenSSL library +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum OpensslError { + /// An unknown error + UnknownError { + /// The library reporting the error + library: String, + /// The function reporting the error + function: String, + /// The reason for the error + reason: String + } +} + +fn get_lib(err: c_ulong) -> String { + unsafe { + let bytes = c_str_to_bytes(&ffi::ERR_lib_error_string(err)).to_vec(); + String::from_utf8(bytes).unwrap() + } +} + +fn get_func(err: c_ulong) -> String { + unsafe { + let bytes = c_str_to_bytes(&ffi::ERR_func_error_string(err)).to_vec(); + String::from_utf8(bytes).unwrap() + } +} + +fn get_reason(err: c_ulong) -> String { + unsafe { + let bytes = c_str_to_bytes(&ffi::ERR_reason_error_string(err)).to_vec(); + String::from_utf8(bytes).unwrap() + } +} + +impl SslError { + /// Creates a new `OpenSslErrors` with the current contents of the error + /// stack. + pub fn get() -> SslError { + let mut errs = vec!(); + loop { + match unsafe { ffi::ERR_get_error() } { + 0 => break, + err => errs.push(SslError::from_error_code(err)) + } + } + OpenSslErrors(errs) + } + + /// Creates an `SslError` from the raw numeric error code. + pub fn from_error(err: c_ulong) -> SslError { + OpenSslErrors(vec![SslError::from_error_code(err)]) + } + + fn from_error_code(err: c_ulong) -> OpensslError { + ffi::init(); + UnknownError { + library: get_lib(err), + function: get_func(err), + reason: get_reason(err) + } + } +} + +#[test] +fn test_uknown_error_should_have_correct_messages() { + let errs = match SslError::from_error(336032784) { + OpenSslErrors(errs) => errs, + _ => panic!("This should always be an `OpenSslErrors` variant.") + }; + + let UnknownError { ref library, ref function, ref reason } = errs[0]; + + assert_eq!(library.as_slice(), "SSL routines"); + assert_eq!(function.as_slice(), "SSL23_GET_SERVER_HELLO"); + assert_eq!(reason.as_slice(), "sslv3 alert handshake failure"); +} -- cgit v1.2.3