diff --git a/boring/src/error.rs b/boring/src/error.rs index b20eff33..0c35e29e 100644 --- a/boring/src/error.rs +++ b/boring/src/error.rs @@ -66,7 +66,7 @@ impl fmt::Display for ErrorStack { let mut first = true; for err in &self.0 { if !first { - fmt.write_str(", ")?; + fmt.write_str("\n--\n")?; } write!(fmt, "{}", err)?; first = false; diff --git a/boring/src/ssl/error.rs b/boring/src/ssl/error.rs index 91bdbb4e..674e221c 100644 --- a/boring/src/ssl/error.rs +++ b/boring/src/ssl/error.rs @@ -4,6 +4,7 @@ use std::error; use std::error::Error as StdError; use std::fmt; use std::io; +use std::path::Path; use error::ErrorStack; use ssl::MidHandshakeSslStream; @@ -150,29 +151,63 @@ impl StdError for HandshakeError { } } -impl fmt::Display for HandshakeError { +impl fmt::Display for HandshakeError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - HandshakeError::SetupFailure(ref e) => write!(f, "stream setup failed: {}", e)?, - HandshakeError::Failure(ref s) => { - write!(f, "the handshake failed: {}", s.error())?; - let verify = s.ssl().verify_result(); - if verify != X509VerifyResult::OK { - write!(f, ": {}", verify)?; - } + HandshakeError::SetupFailure(ref e) => { + write!(f, "TLS stream setup failed:\n\n{}", e) } + HandshakeError::Failure(ref s) => fmt_mid_handshake_error(s, f, "TLS handshake failed"), HandshakeError::WouldBlock(ref s) => { - write!(f, "the handshake was interrupted: {}", s.error())?; - let verify = s.ssl().verify_result(); - if verify != X509VerifyResult::OK { - write!(f, ": {}", verify)?; - } + fmt_mid_handshake_error(s, f, "TLS handshake interrupted") } } - Ok(()) } } +fn fmt_mid_handshake_error( + s: &MidHandshakeSslStream, + f: &mut fmt::Formatter, + prefix: &str, +) -> fmt::Result { + match s.ssl().verify_result() { + X509VerifyResult::OK => write!(f, "{}", prefix)?, + verify => write!(f, "{}: cert verification failed - {}", prefix, verify)?, + } + + if let Some(error) = s.error().io_error() { + return write!(f, " ({})", error); + } + + if let Some(error) = s.error().ssl_error() { + let errors = error.errors(); + + if errors.is_empty() { + return Ok(()); + } + + f.write_str(":\n")?; + + for error in errors { + let path = error.file(); + let file = Path::new(path) + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or(path); + + write!( + f, + "\n{} [{}] ({}:{})", + error.reason().unwrap_or("unknown error"), + error.code(), + file, + error.line() + )?; + } + } + Ok(()) +} + impl From for HandshakeError { fn from(e: ErrorStack) -> HandshakeError { HandshakeError::SetupFailure(e) diff --git a/boring/src/ssl/mod.rs b/boring/src/ssl/mod.rs index c93cbf5c..a3bbc48f 100644 --- a/boring/src/ssl/mod.rs +++ b/boring/src/ssl/mod.rs @@ -2876,6 +2876,11 @@ impl MidHandshakeSslStream { self.stream.into_inner() } + /// Returns both the error and the source data stream, consuming `self`. + pub fn into_parts(self) -> (Error, S) { + (self.error, self.stream.into_inner()) + } + /// Restarts the handshake process. /// /// This corresponds to [`SSL_do_handshake`]. diff --git a/tokio-boring/src/lib.rs b/tokio-boring/src/lib.rs index 750e1ee1..1ed5c25a 100644 --- a/tokio-boring/src/lib.rs +++ b/tokio-boring/src/lib.rs @@ -277,13 +277,21 @@ impl HandshakeError { } } - /// Converts error to the source data stream tha was used for the handshake. + /// Converts error to the source data stream that was used for the handshake. pub fn into_source_stream(self) -> Option { match self.0 { ssl::HandshakeError::Failure(s) => Some(s.into_source_stream().stream), _ => None, } } + + /// Returns a reference to the source data stream. + pub fn as_source_stream(&self) -> Option<&S> { + match &self.0 { + ssl::HandshakeError::Failure(s) => Some(&s.get_ref().stream), + _ => None, + } + } } impl fmt::Debug for HandshakeError