1use libc::c_int;
2use std::error;
3use std::error::Error as StdError;
4use std::fmt;
5use std::io;
6
7use crate::error::ErrorStack;
8use crate::ssl::MidHandshakeSslStream;
9use crate::x509::X509VerifyResult;
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13pub struct ErrorCode(c_int);
14
15impl ErrorCode {
16 pub const ZERO_RETURN: ErrorCode = ErrorCode(ffi::SSL_ERROR_ZERO_RETURN);
18
19 #[cfg(ossl110)]
26 pub const WANT_ASYNC: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_ASYNC);
27
28 #[cfg(ossl110)]
36 pub const WANT_ASYNC_JOB: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_ASYNC_JOB);
37
38 pub const WANT_READ: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_READ);
42
43 pub const WANT_WRITE: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_WRITE);
47
48 pub const SYSCALL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SYSCALL);
50
51 pub const SSL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SSL);
53
54 #[cfg(ossl111)]
58 pub const WANT_CLIENT_HELLO_CB: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_CLIENT_HELLO_CB);
59
60 #[cfg(any(boringssl, awslc))]
67 pub const PENDING_CERTIFICATE: ErrorCode = ErrorCode(ffi::SSL_ERROR_PENDING_CERTIFICATE);
68
69 #[cfg(any(boringssl, awslc))]
75 pub const WANT_PRIVATE_KEY_OPERATION: ErrorCode =
76 ErrorCode(ffi::SSL_ERROR_WANT_PRIVATE_KEY_OPERATION);
77
78 pub fn from_raw(raw: c_int) -> ErrorCode {
79 ErrorCode(raw)
80 }
81
82 #[allow(clippy::trivially_copy_pass_by_ref)]
83 pub fn as_raw(&self) -> c_int {
84 self.0
85 }
86}
87
88#[derive(Debug)]
89pub(crate) enum InnerError {
90 Io(io::Error),
91 Ssl(ErrorStack),
92}
93
94#[derive(Debug)]
96pub struct Error {
97 pub(crate) code: ErrorCode,
98 pub(crate) cause: Option<InnerError>,
99}
100
101impl Error {
102 pub fn code(&self) -> ErrorCode {
103 self.code
104 }
105
106 pub fn io_error(&self) -> Option<&io::Error> {
107 match self.cause {
108 Some(InnerError::Io(ref e)) => Some(e),
109 _ => None,
110 }
111 }
112
113 pub fn into_io_error(self) -> Result<io::Error, Error> {
114 match self.cause {
115 Some(InnerError::Io(e)) => Ok(e),
116 _ => Err(self),
117 }
118 }
119
120 pub fn ssl_error(&self) -> Option<&ErrorStack> {
121 match self.cause {
122 Some(InnerError::Ssl(ref e)) => Some(e),
123 _ => None,
124 }
125 }
126}
127
128impl From<ErrorStack> for Error {
129 fn from(e: ErrorStack) -> Error {
130 Error {
131 code: ErrorCode::SSL,
132 cause: Some(InnerError::Ssl(e)),
133 }
134 }
135}
136
137impl fmt::Display for Error {
138 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
139 match self.code {
140 ErrorCode::ZERO_RETURN => fmt.write_str("the SSL session has been shut down"),
141 ErrorCode::WANT_READ => match self.io_error() {
142 Some(_) => fmt.write_str("a nonblocking read call would have blocked"),
143 None => fmt.write_str("the operation should be retried"),
144 },
145 ErrorCode::WANT_WRITE => match self.io_error() {
146 Some(_) => fmt.write_str("a nonblocking write call would have blocked"),
147 None => fmt.write_str("the operation should be retried"),
148 },
149 ErrorCode::SYSCALL => match self.io_error() {
150 Some(err) => write!(fmt, "{}", err),
151 None => fmt.write_str("unexpected EOF"),
152 },
153 ErrorCode::SSL => match self.ssl_error() {
154 Some(e) => write!(fmt, "{}", e),
155 None => fmt.write_str("OpenSSL error"),
156 },
157 ErrorCode(code) => write!(fmt, "unknown error code {}", code),
158 }
159 }
160}
161
162impl error::Error for Error {
163 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
164 match self.cause {
165 Some(InnerError::Io(ref e)) => Some(e),
166 Some(InnerError::Ssl(ref e)) => Some(e),
167 None => None,
168 }
169 }
170}
171
172#[derive(Debug)]
175pub enum HandshakeError<S> {
176 SetupFailure(ErrorStack),
178 Failure(MidHandshakeSslStream<S>),
180 WouldBlock(MidHandshakeSslStream<S>),
184}
185
186impl<S: fmt::Debug> StdError for HandshakeError<S> {
187 fn source(&self) -> Option<&(dyn StdError + 'static)> {
188 match *self {
189 HandshakeError::SetupFailure(ref e) => Some(e),
190 HandshakeError::Failure(ref s) | HandshakeError::WouldBlock(ref s) => Some(s.error()),
191 }
192 }
193}
194
195impl<S: fmt::Debug> fmt::Display for HandshakeError<S> {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 match *self {
198 HandshakeError::SetupFailure(ref e) => write!(f, "stream setup failed: {}", e)?,
199 HandshakeError::Failure(ref s) => {
200 write!(f, "the handshake failed: {}", s.error())?;
201 let verify = s.ssl().verify_result();
202 if verify != X509VerifyResult::OK {
203 write!(f, ": {}", verify)?;
204 }
205 }
206 HandshakeError::WouldBlock(ref s) => {
207 write!(f, "the handshake was interrupted: {}", s.error())?;
208 let verify = s.ssl().verify_result();
209 if verify != X509VerifyResult::OK {
210 write!(f, ": {}", verify)?;
211 }
212 }
213 }
214 Ok(())
215 }
216}
217
218impl<S> From<ErrorStack> for HandshakeError<S> {
219 fn from(e: ErrorStack) -> HandshakeError<S> {
220 HandshakeError::SetupFailure(e)
221 }
222}