• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use core::fmt;
15 use std::error::Error;
16 use std::io;
17 
18 use libc::c_int;
19 
20 use super::MidHandshakeSslStream;
21 use crate::c_openssl::error::ErrorStack;
22 
23 #[derive(Debug)]
24 pub(crate) struct SslError {
25     pub(crate) code: SslErrorCode,
26     pub(crate) internal: Option<InternalError>,
27 }
28 
29 #[derive(Debug)]
30 pub(crate) enum InternalError {
31     Io(io::Error),
32     Ssl(ErrorStack),
33 }
34 
35 impl SslError {
code(&self) -> SslErrorCode36     pub(crate) fn code(&self) -> SslErrorCode {
37         self.code
38     }
39 
into_io_error(self) -> Result<io::Error, SslError>40     pub(crate) fn into_io_error(self) -> Result<io::Error, SslError> {
41         match self.internal {
42             Some(InternalError::Io(e)) => Ok(e),
43             _ => Err(self),
44         }
45     }
46 
get_io_error(&self) -> Option<&io::Error>47     pub(crate) fn get_io_error(&self) -> Option<&io::Error> {
48         match self.internal {
49             Some(InternalError::Io(ref e)) => Some(e),
50             _ => None,
51         }
52     }
53 }
54 
55 impl Error for SslError {
source(&self) -> Option<&(dyn Error + 'static)>56     fn source(&self) -> Option<&(dyn Error + 'static)> {
57         match self.internal {
58             Some(InternalError::Io(ref e)) => Some(e),
59             Some(InternalError::Ssl(ref e)) => Some(e),
60             None => None,
61         }
62     }
63 }
64 
65 impl fmt::Display for SslError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result66     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67         match self.code {
68             SslErrorCode::ZERO_RETURN => write!(f, "SSL session has been closed"),
69             SslErrorCode::SYSCALL => {
70                 if let Some(InternalError::Io(e)) = &self.internal {
71                     write!(f, "SslCode[{}], IO Error: {}", self.code, e)
72                 } else {
73                     write!(f, "SslCode[{}], Unexpected EOF", self.code)
74                 }
75             }
76             SslErrorCode::SSL => {
77                 if let Some(InternalError::Ssl(e)) = &self.internal {
78                     write!(f, "ErrorStack: {e}")
79                 } else {
80                     write!(f, "SslCode: [{}]", self.code)
81                 }
82             }
83             SslErrorCode::WANT_READ => {
84                 if let Some(InternalError::Io(e)) = &self.internal {
85                     write!(f, "SslCode[{}], IO Error: {}", self.code, e)
86                 } else {
87                     write!(
88                         f,
89                         "SslCode[{}], Read operation should be retried",
90                         self.code
91                     )
92                 }
93             }
94             SslErrorCode::WANT_WRITE => {
95                 if let Some(InternalError::Io(e)) = &self.internal {
96                     write!(f, "SslCode[{}], IO Error: {}", self.code, e)
97                 } else {
98                     write!(
99                         f,
100                         "SslCode[{}], Write operation should be retried",
101                         self.code
102                     )
103                 }
104             }
105             _ => {
106                 write!(f, "Unknown SslCode[{}]", self.code)
107             }
108         }
109     }
110 }
111 
112 const SSL_ERROR_SSL: c_int = 1;
113 const SSL_ERROR_SYSCALL: c_int = 5;
114 const SSL_ERROR_WANT_READ: c_int = 2;
115 const SSL_ERROR_WANT_WRITE: c_int = 3;
116 const SSL_ERROR_ZERO_RETURN: c_int = 6;
117 
118 #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
119 pub(crate) struct SslErrorCode(c_int);
120 
121 impl SslErrorCode {
122     pub(crate) const ZERO_RETURN: SslErrorCode = SslErrorCode(SSL_ERROR_ZERO_RETURN);
123     pub(crate) const WANT_READ: SslErrorCode = SslErrorCode(SSL_ERROR_WANT_READ);
124     pub(crate) const WANT_WRITE: SslErrorCode = SslErrorCode(SSL_ERROR_WANT_WRITE);
125     pub(crate) const SYSCALL: SslErrorCode = SslErrorCode(SSL_ERROR_SYSCALL);
126     pub(crate) const SSL: SslErrorCode = SslErrorCode(SSL_ERROR_SSL);
127 
from_int(err: c_int) -> SslErrorCode128     pub(crate) fn from_int(err: c_int) -> SslErrorCode {
129         SslErrorCode(err)
130     }
131 }
132 
133 impl fmt::Display for SslErrorCode {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result134     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135         write!(f, "{}", self.0)
136     }
137 }
138 
139 #[derive(Debug)]
140 pub(crate) enum HandshakeError<S> {
141     SetupFailure(ErrorStack),
142     Failure(MidHandshakeSslStream<S>),
143     WouldBlock(MidHandshakeSslStream<S>),
144 }
145 
146 impl<S> From<ErrorStack> for HandshakeError<S> {
from(e: ErrorStack) -> HandshakeError<S>147     fn from(e: ErrorStack) -> HandshakeError<S> {
148         HandshakeError::SetupFailure(e)
149     }
150 }
151 
152 impl<S: fmt::Debug> Error for HandshakeError<S> {
source(&self) -> Option<&(dyn Error + 'static)>153     fn source(&self) -> Option<&(dyn Error + 'static)> {
154         match *self {
155             HandshakeError::SetupFailure(ref e) => Some(e),
156             HandshakeError::Failure(ref s) | HandshakeError::WouldBlock(ref s) => Some(s.error()),
157         }
158     }
159 }
160 
161 impl<S: fmt::Debug> fmt::Display for HandshakeError<S> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result162     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163         match *self {
164             HandshakeError::SetupFailure(ref e) => write!(f, "Stream setup failed: {e}")?,
165             HandshakeError::Failure(ref s) => {
166                 write!(f, "Handshake failed: {}", s.error())?;
167             }
168             HandshakeError::WouldBlock(ref s) => {
169                 write!(f, "Handshake was interrupted: {}", s.error())?;
170             }
171         }
172         Ok(())
173     }
174 }
175