192f3ab15Sopenharmony_ciuse libc::c_int; 292f3ab15Sopenharmony_ciuse std::error; 392f3ab15Sopenharmony_ciuse std::error::Error as StdError; 492f3ab15Sopenharmony_ciuse std::fmt; 592f3ab15Sopenharmony_ciuse std::io; 692f3ab15Sopenharmony_ci 792f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 892f3ab15Sopenharmony_ciuse crate::ssl::MidHandshakeSslStream; 992f3ab15Sopenharmony_ciuse crate::x509::X509VerifyResult; 1092f3ab15Sopenharmony_ci 1192f3ab15Sopenharmony_ci/// An error code returned from SSL functions. 1292f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)] 1392f3ab15Sopenharmony_cipub struct ErrorCode(c_int); 1492f3ab15Sopenharmony_ci 1592f3ab15Sopenharmony_ciimpl ErrorCode { 1692f3ab15Sopenharmony_ci /// The SSL session has been closed. 1792f3ab15Sopenharmony_ci pub const ZERO_RETURN: ErrorCode = ErrorCode(ffi::SSL_ERROR_ZERO_RETURN); 1892f3ab15Sopenharmony_ci 1992f3ab15Sopenharmony_ci /// An attempt to read data from the underlying socket returned `WouldBlock`. 2092f3ab15Sopenharmony_ci /// 2192f3ab15Sopenharmony_ci /// Wait for read readiness and retry the operation. 2292f3ab15Sopenharmony_ci pub const WANT_READ: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_READ); 2392f3ab15Sopenharmony_ci 2492f3ab15Sopenharmony_ci /// An attempt to write data to the underlying socket returned `WouldBlock`. 2592f3ab15Sopenharmony_ci /// 2692f3ab15Sopenharmony_ci /// Wait for write readiness and retry the operation. 2792f3ab15Sopenharmony_ci pub const WANT_WRITE: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_WRITE); 2892f3ab15Sopenharmony_ci 2992f3ab15Sopenharmony_ci /// A non-recoverable IO error occurred. 3092f3ab15Sopenharmony_ci pub const SYSCALL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SYSCALL); 3192f3ab15Sopenharmony_ci 3292f3ab15Sopenharmony_ci /// An error occurred in the SSL library. 3392f3ab15Sopenharmony_ci pub const SSL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SSL); 3492f3ab15Sopenharmony_ci 3592f3ab15Sopenharmony_ci /// The client hello callback indicated that it needed to be retried. 3692f3ab15Sopenharmony_ci /// 3792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 3892f3ab15Sopenharmony_ci #[cfg(ossl111)] 3992f3ab15Sopenharmony_ci pub const WANT_CLIENT_HELLO_CB: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_CLIENT_HELLO_CB); 4092f3ab15Sopenharmony_ci 4192f3ab15Sopenharmony_ci pub fn from_raw(raw: c_int) -> ErrorCode { 4292f3ab15Sopenharmony_ci ErrorCode(raw) 4392f3ab15Sopenharmony_ci } 4492f3ab15Sopenharmony_ci 4592f3ab15Sopenharmony_ci #[allow(clippy::trivially_copy_pass_by_ref)] 4692f3ab15Sopenharmony_ci pub fn as_raw(&self) -> c_int { 4792f3ab15Sopenharmony_ci self.0 4892f3ab15Sopenharmony_ci } 4992f3ab15Sopenharmony_ci} 5092f3ab15Sopenharmony_ci 5192f3ab15Sopenharmony_ci#[derive(Debug)] 5292f3ab15Sopenharmony_cipub(crate) enum InnerError { 5392f3ab15Sopenharmony_ci Io(io::Error), 5492f3ab15Sopenharmony_ci Ssl(ErrorStack), 5592f3ab15Sopenharmony_ci} 5692f3ab15Sopenharmony_ci 5792f3ab15Sopenharmony_ci/// An SSL error. 5892f3ab15Sopenharmony_ci#[derive(Debug)] 5992f3ab15Sopenharmony_cipub struct Error { 6092f3ab15Sopenharmony_ci pub(crate) code: ErrorCode, 6192f3ab15Sopenharmony_ci pub(crate) cause: Option<InnerError>, 6292f3ab15Sopenharmony_ci} 6392f3ab15Sopenharmony_ci 6492f3ab15Sopenharmony_ciimpl Error { 6592f3ab15Sopenharmony_ci pub fn code(&self) -> ErrorCode { 6692f3ab15Sopenharmony_ci self.code 6792f3ab15Sopenharmony_ci } 6892f3ab15Sopenharmony_ci 6992f3ab15Sopenharmony_ci pub fn io_error(&self) -> Option<&io::Error> { 7092f3ab15Sopenharmony_ci match self.cause { 7192f3ab15Sopenharmony_ci Some(InnerError::Io(ref e)) => Some(e), 7292f3ab15Sopenharmony_ci _ => None, 7392f3ab15Sopenharmony_ci } 7492f3ab15Sopenharmony_ci } 7592f3ab15Sopenharmony_ci 7692f3ab15Sopenharmony_ci pub fn into_io_error(self) -> Result<io::Error, Error> { 7792f3ab15Sopenharmony_ci match self.cause { 7892f3ab15Sopenharmony_ci Some(InnerError::Io(e)) => Ok(e), 7992f3ab15Sopenharmony_ci _ => Err(self), 8092f3ab15Sopenharmony_ci } 8192f3ab15Sopenharmony_ci } 8292f3ab15Sopenharmony_ci 8392f3ab15Sopenharmony_ci pub fn ssl_error(&self) -> Option<&ErrorStack> { 8492f3ab15Sopenharmony_ci match self.cause { 8592f3ab15Sopenharmony_ci Some(InnerError::Ssl(ref e)) => Some(e), 8692f3ab15Sopenharmony_ci _ => None, 8792f3ab15Sopenharmony_ci } 8892f3ab15Sopenharmony_ci } 8992f3ab15Sopenharmony_ci} 9092f3ab15Sopenharmony_ci 9192f3ab15Sopenharmony_ciimpl From<ErrorStack> for Error { 9292f3ab15Sopenharmony_ci fn from(e: ErrorStack) -> Error { 9392f3ab15Sopenharmony_ci Error { 9492f3ab15Sopenharmony_ci code: ErrorCode::SSL, 9592f3ab15Sopenharmony_ci cause: Some(InnerError::Ssl(e)), 9692f3ab15Sopenharmony_ci } 9792f3ab15Sopenharmony_ci } 9892f3ab15Sopenharmony_ci} 9992f3ab15Sopenharmony_ci 10092f3ab15Sopenharmony_ciimpl fmt::Display for Error { 10192f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 10292f3ab15Sopenharmony_ci match self.code { 10392f3ab15Sopenharmony_ci ErrorCode::ZERO_RETURN => fmt.write_str("the SSL session has been shut down"), 10492f3ab15Sopenharmony_ci ErrorCode::WANT_READ => match self.io_error() { 10592f3ab15Sopenharmony_ci Some(_) => fmt.write_str("a nonblocking read call would have blocked"), 10692f3ab15Sopenharmony_ci None => fmt.write_str("the operation should be retried"), 10792f3ab15Sopenharmony_ci }, 10892f3ab15Sopenharmony_ci ErrorCode::WANT_WRITE => match self.io_error() { 10992f3ab15Sopenharmony_ci Some(_) => fmt.write_str("a nonblocking write call would have blocked"), 11092f3ab15Sopenharmony_ci None => fmt.write_str("the operation should be retried"), 11192f3ab15Sopenharmony_ci }, 11292f3ab15Sopenharmony_ci ErrorCode::SYSCALL => match self.io_error() { 11392f3ab15Sopenharmony_ci Some(err) => write!(fmt, "{}", err), 11492f3ab15Sopenharmony_ci None => fmt.write_str("unexpected EOF"), 11592f3ab15Sopenharmony_ci }, 11692f3ab15Sopenharmony_ci ErrorCode::SSL => match self.ssl_error() { 11792f3ab15Sopenharmony_ci Some(e) => write!(fmt, "{}", e), 11892f3ab15Sopenharmony_ci None => fmt.write_str("OpenSSL error"), 11992f3ab15Sopenharmony_ci }, 12092f3ab15Sopenharmony_ci ErrorCode(code) => write!(fmt, "unknown error code {}", code), 12192f3ab15Sopenharmony_ci } 12292f3ab15Sopenharmony_ci } 12392f3ab15Sopenharmony_ci} 12492f3ab15Sopenharmony_ci 12592f3ab15Sopenharmony_ciimpl error::Error for Error { 12692f3ab15Sopenharmony_ci fn source(&self) -> Option<&(dyn error::Error + 'static)> { 12792f3ab15Sopenharmony_ci match self.cause { 12892f3ab15Sopenharmony_ci Some(InnerError::Io(ref e)) => Some(e), 12992f3ab15Sopenharmony_ci Some(InnerError::Ssl(ref e)) => Some(e), 13092f3ab15Sopenharmony_ci None => None, 13192f3ab15Sopenharmony_ci } 13292f3ab15Sopenharmony_ci } 13392f3ab15Sopenharmony_ci} 13492f3ab15Sopenharmony_ci 13592f3ab15Sopenharmony_ci/// An error or intermediate state after a TLS handshake attempt. 13692f3ab15Sopenharmony_ci// FIXME overhaul 13792f3ab15Sopenharmony_ci#[derive(Debug)] 13892f3ab15Sopenharmony_cipub enum HandshakeError<S> { 13992f3ab15Sopenharmony_ci /// Setup failed. 14092f3ab15Sopenharmony_ci SetupFailure(ErrorStack), 14192f3ab15Sopenharmony_ci /// The handshake failed. 14292f3ab15Sopenharmony_ci Failure(MidHandshakeSslStream<S>), 14392f3ab15Sopenharmony_ci /// The handshake encountered a `WouldBlock` error midway through. 14492f3ab15Sopenharmony_ci /// 14592f3ab15Sopenharmony_ci /// This error will never be returned for blocking streams. 14692f3ab15Sopenharmony_ci WouldBlock(MidHandshakeSslStream<S>), 14792f3ab15Sopenharmony_ci} 14892f3ab15Sopenharmony_ci 14992f3ab15Sopenharmony_ciimpl<S: fmt::Debug> StdError for HandshakeError<S> { 15092f3ab15Sopenharmony_ci fn source(&self) -> Option<&(dyn StdError + 'static)> { 15192f3ab15Sopenharmony_ci match *self { 15292f3ab15Sopenharmony_ci HandshakeError::SetupFailure(ref e) => Some(e), 15392f3ab15Sopenharmony_ci HandshakeError::Failure(ref s) | HandshakeError::WouldBlock(ref s) => Some(s.error()), 15492f3ab15Sopenharmony_ci } 15592f3ab15Sopenharmony_ci } 15692f3ab15Sopenharmony_ci} 15792f3ab15Sopenharmony_ci 15892f3ab15Sopenharmony_ciimpl<S: fmt::Debug> fmt::Display for HandshakeError<S> { 15992f3ab15Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 16092f3ab15Sopenharmony_ci match *self { 16192f3ab15Sopenharmony_ci HandshakeError::SetupFailure(ref e) => write!(f, "stream setup failed: {}", e)?, 16292f3ab15Sopenharmony_ci HandshakeError::Failure(ref s) => { 16392f3ab15Sopenharmony_ci write!(f, "the handshake failed: {}", s.error())?; 16492f3ab15Sopenharmony_ci let verify = s.ssl().verify_result(); 16592f3ab15Sopenharmony_ci if verify != X509VerifyResult::OK { 16692f3ab15Sopenharmony_ci write!(f, ": {}", verify)?; 16792f3ab15Sopenharmony_ci } 16892f3ab15Sopenharmony_ci } 16992f3ab15Sopenharmony_ci HandshakeError::WouldBlock(ref s) => { 17092f3ab15Sopenharmony_ci write!(f, "the handshake was interrupted: {}", s.error())?; 17192f3ab15Sopenharmony_ci let verify = s.ssl().verify_result(); 17292f3ab15Sopenharmony_ci if verify != X509VerifyResult::OK { 17392f3ab15Sopenharmony_ci write!(f, ": {}", verify)?; 17492f3ab15Sopenharmony_ci } 17592f3ab15Sopenharmony_ci } 17692f3ab15Sopenharmony_ci } 17792f3ab15Sopenharmony_ci Ok(()) 17892f3ab15Sopenharmony_ci } 17992f3ab15Sopenharmony_ci} 18092f3ab15Sopenharmony_ci 18192f3ab15Sopenharmony_ciimpl<S> From<ErrorStack> for HandshakeError<S> { 18292f3ab15Sopenharmony_ci fn from(e: ErrorStack) -> HandshakeError<S> { 18392f3ab15Sopenharmony_ci HandshakeError::SetupFailure(e) 18492f3ab15Sopenharmony_ci } 18592f3ab15Sopenharmony_ci} 186