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