1 use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
2 use sct;
3 use std::error::Error;
4 use std::fmt;
5 use webpki;
6 
7 /// rustls reports protocol errors using this type.
8 #[derive(Debug, PartialEq, Clone)]
9 pub enum TLSError {
10     /// We received a TLS message that isn't valid right now.
11     /// `expect_types` lists the message types we can expect right now.
12     /// `got_type` is the type we found.  This error is typically
13     /// caused by a buggy TLS stack (the peer or this one), a broken
14     /// network, or an attack.
15     InappropriateMessage {
16         /// Which types we expected
17         expect_types: Vec<ContentType>,
18         /// What type we received
19         got_type: ContentType,
20     },
21 
22     /// We received a TLS handshake message that isn't valid right now.
23     /// `expect_types` lists the handshake message types we can expect
24     /// right now.  `got_type` is the type we found.
25     InappropriateHandshakeMessage {
26         /// Which handshake type we expected
27         expect_types: Vec<HandshakeType>,
28         /// What handshake type we received
29         got_type: HandshakeType,
30     },
31 
32     /// The peer sent us a syntactically incorrect TLS message.
33     CorruptMessage,
34 
35     /// The peer sent us a TLS message with invalid contents.
36     CorruptMessagePayload(ContentType),
37 
38     /// The peer didn't give us any certificates.
39     NoCertificatesPresented,
40 
41     /// We couldn't decrypt a message.  This is invariably fatal.
42     DecryptError,
43 
44     /// The peer doesn't support a protocol version/feature we require.
45     /// The parameter gives a hint as to what version/feature it is.
46     PeerIncompatibleError(String),
47 
48     /// The peer deviated from the standard TLS protocol.
49     /// The parameter gives a hint where.
50     PeerMisbehavedError(String),
51 
52     /// We received a fatal alert.  This means the peer is unhappy.
53     AlertReceived(AlertDescription),
54 
55     /// The presented certificate chain is invalid.
56     WebPKIError(webpki::Error),
57 
58     /// The presented SCT(s) were invalid.
59     InvalidSCT(sct::Error),
60 
61     /// A catch-all error for unlikely errors.
62     General(String),
63 
64     /// We failed to figure out what time it currently is.
65     FailedToGetCurrentTime,
66 
67     /// This function doesn't work until the TLS handshake
68     /// is complete.
69     HandshakeNotComplete,
70 
71     /// The peer sent an oversized record/fragment.
72     PeerSentOversizedRecord,
73 
74     /// An incoming connection did not support any known application protocol.
75     NoApplicationProtocol,
76 }
77 
join<T: fmt::Debug>(items: &[T]) -> String78 fn join<T: fmt::Debug>(items: &[T]) -> String {
79     items
80         .iter()
81         .map(|x| format!("{:?}", x))
82         .collect::<Vec<String>>()
83         .join(" or ")
84 }
85 
86 impl fmt::Display for TLSError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result87     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88         match *self {
89             TLSError::InappropriateMessage {
90                 ref expect_types,
91                 ref got_type,
92             } => write!(
93                 f,
94                 "received unexpected message: got {:?} when expecting {}",
95                 got_type,
96                 join::<ContentType>(expect_types)
97             ),
98             TLSError::InappropriateHandshakeMessage {
99                 ref expect_types,
100                 ref got_type,
101             } => write!(
102                 f,
103                 "received unexpected handshake message: got {:?} when expecting {}",
104                 got_type,
105                 join::<HandshakeType>(expect_types)
106             ),
107             TLSError::CorruptMessagePayload(ref typ) => {
108                 write!(f, "received corrupt message of type {:?}", typ)
109             }
110             TLSError::PeerIncompatibleError(ref why) => write!(f, "peer is incompatible: {}", why),
111             TLSError::PeerMisbehavedError(ref why) => write!(f, "peer misbehaved: {}", why),
112             TLSError::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
113             TLSError::WebPKIError(ref err) => write!(f, "invalid certificate: {:?}", err),
114             TLSError::CorruptMessage => write!(f, "received corrupt message"),
115             TLSError::NoCertificatesPresented => write!(f, "peer sent no certificates"),
116             TLSError::DecryptError => write!(f, "cannot decrypt peer's message"),
117             TLSError::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
118             TLSError::HandshakeNotComplete => write!(f, "handshake not complete"),
119             TLSError::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
120             TLSError::InvalidSCT(ref err) => write!(f, "invalid certificate timestamp: {:?}", err),
121             TLSError::FailedToGetCurrentTime => write!(f, "failed to get current time"),
122             TLSError::General(ref err) => write!(f, "unexpected error: {}", err), // (please file a bug)
123         }
124     }
125 }
126 
127 impl Error for TLSError {}
128 
129 #[cfg(test)]
130 mod tests {
131     #[test]
smoke()132     fn smoke() {
133         use super::TLSError;
134         use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
135         use sct;
136         use webpki;
137 
138         let all = vec![
139             TLSError::InappropriateMessage {
140                 expect_types: vec![ContentType::Alert],
141                 got_type: ContentType::Handshake,
142             },
143             TLSError::InappropriateHandshakeMessage {
144                 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
145                 got_type: HandshakeType::ServerHello,
146             },
147             TLSError::CorruptMessage,
148             TLSError::CorruptMessagePayload(ContentType::Alert),
149             TLSError::NoCertificatesPresented,
150             TLSError::DecryptError,
151             TLSError::PeerIncompatibleError("no tls1.2".to_string()),
152             TLSError::PeerMisbehavedError("inconsistent something".to_string()),
153             TLSError::AlertReceived(AlertDescription::ExportRestriction),
154             TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid),
155             TLSError::InvalidSCT(sct::Error::MalformedSCT),
156             TLSError::General("undocumented error".to_string()),
157             TLSError::FailedToGetCurrentTime,
158             TLSError::HandshakeNotComplete,
159             TLSError::PeerSentOversizedRecord,
160             TLSError::NoApplicationProtocol,
161         ];
162 
163         for err in all {
164             println!("{:?}:", err);
165             println!("  fmt '{}'", err);
166         }
167     }
168 }
169