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