use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
use sct;
use std::error::Error;
use std::fmt;
use webpki;
#[derive(Debug, PartialEq, Clone)]
pub enum TLSError {
InappropriateMessage {
expect_types: Vec<ContentType>,
got_type: ContentType,
},
InappropriateHandshakeMessage {
expect_types: Vec<HandshakeType>,
got_type: HandshakeType,
},
CorruptMessage,
CorruptMessagePayload(ContentType),
NoCertificatesPresented,
DecryptError,
PeerIncompatibleError(String),
PeerMisbehavedError(String),
AlertReceived(AlertDescription),
WebPKIError(webpki::Error),
InvalidSCT(sct::Error),
General(String),
FailedToGetCurrentTime,
HandshakeNotComplete,
PeerSentOversizedRecord,
NoApplicationProtocol,
}
fn join<T: fmt::Debug>(items: &[T]) -> String {
items
.iter()
.map(|x| format!("{:?}", x))
.collect::<Vec<String>>()
.join(" or ")
}
impl fmt::Display for TLSError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TLSError::InappropriateMessage {
ref expect_types,
ref got_type,
} => write!(
f,
"received unexpected message: got {:?} when expecting {}",
got_type,
join::<ContentType>(expect_types)
),
TLSError::InappropriateHandshakeMessage {
ref expect_types,
ref got_type,
} => write!(
f,
"received unexpected handshake message: got {:?} when expecting {}",
got_type,
join::<HandshakeType>(expect_types)
),
TLSError::CorruptMessagePayload(ref typ) => {
write!(f, "received corrupt message of type {:?}", typ)
}
TLSError::PeerIncompatibleError(ref why) => write!(f, "peer is incompatible: {}", why),
TLSError::PeerMisbehavedError(ref why) => write!(f, "peer misbehaved: {}", why),
TLSError::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
TLSError::WebPKIError(ref err) => write!(f, "invalid certificate: {:?}", err),
TLSError::CorruptMessage => write!(f, "received corrupt message"),
TLSError::NoCertificatesPresented => write!(f, "peer sent no certificates"),
TLSError::DecryptError => write!(f, "cannot decrypt peer's message"),
TLSError::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
TLSError::HandshakeNotComplete => write!(f, "handshake not complete"),
TLSError::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
TLSError::InvalidSCT(ref err) => write!(f, "invalid certificate timestamp: {:?}", err),
TLSError::FailedToGetCurrentTime => write!(f, "failed to get current time"),
TLSError::General(ref err) => write!(f, "unexpected error: {}", err), }
}
}
impl Error for TLSError {}
#[cfg(test)]
mod tests {
#[test]
fn smoke() {
use super::TLSError;
use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
use sct;
use webpki;
let all = vec![
TLSError::InappropriateMessage {
expect_types: vec![ContentType::Alert],
got_type: ContentType::Handshake,
},
TLSError::InappropriateHandshakeMessage {
expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
got_type: HandshakeType::ServerHello,
},
TLSError::CorruptMessage,
TLSError::CorruptMessagePayload(ContentType::Alert),
TLSError::NoCertificatesPresented,
TLSError::DecryptError,
TLSError::PeerIncompatibleError("no tls1.2".to_string()),
TLSError::PeerMisbehavedError("inconsistent something".to_string()),
TLSError::AlertReceived(AlertDescription::ExportRestriction),
TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid),
TLSError::InvalidSCT(sct::Error::MalformedSCT),
TLSError::General("undocumented error".to_string()),
TLSError::FailedToGetCurrentTime,
TLSError::HandshakeNotComplete,
TLSError::PeerSentOversizedRecord,
TLSError::NoApplicationProtocol,
];
for err in all {
println!("{:?}:", err);
println!(" fmt '{}'", err);
}
}
}