1#[cfg(test)]
2mod alert_test;
3
4use super::content::*;
5use shared::error::Result;
6
7use byteorder::{ReadBytesExt, WriteBytesExt};
8use std::fmt;
9use std::io::{Read, Write};
10
11#[derive(Copy, Clone, PartialEq, Debug)]
12pub(crate) enum AlertLevel {
13 Warning = 1,
14 Fatal = 2,
15 Invalid,
16}
17
18impl fmt::Display for AlertLevel {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 match *self {
21 AlertLevel::Warning => write!(f, "LevelWarning"),
22 AlertLevel::Fatal => write!(f, "LevelFatal"),
23 _ => write!(f, "Invalid alert level"),
24 }
25 }
26}
27
28impl From<u8> for AlertLevel {
29 fn from(val: u8) -> Self {
30 match val {
31 1 => AlertLevel::Warning,
32 2 => AlertLevel::Fatal,
33 _ => AlertLevel::Invalid,
34 }
35 }
36}
37
38#[derive(Copy, Clone, PartialEq, Debug)]
39pub(crate) enum AlertDescription {
40 CloseNotify = 0,
41 UnexpectedMessage = 10,
42 BadRecordMac = 20,
43 DecryptionFailed = 21,
44 RecordOverflow = 22,
45 DecompressionFailure = 30,
46 HandshakeFailure = 40,
47 NoCertificate = 41,
48 BadCertificate = 42,
49 UnsupportedCertificate = 43,
50 CertificateRevoked = 44,
51 CertificateExpired = 45,
52 CertificateUnknown = 46,
53 IllegalParameter = 47,
54 UnknownCa = 48,
55 AccessDenied = 49,
56 DecodeError = 50,
57 DecryptError = 51,
58 ExportRestriction = 60,
59 ProtocolVersion = 70,
60 InsufficientSecurity = 71,
61 InternalError = 80,
62 UserCanceled = 90,
63 NoRenegotiation = 100,
64 UnsupportedExtension = 110,
65 UnknownPskIdentity = 115,
66 Invalid,
67}
68
69impl fmt::Display for AlertDescription {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match *self {
72 AlertDescription::CloseNotify => write!(f, "CloseNotify"),
73 AlertDescription::UnexpectedMessage => write!(f, "UnexpectedMessage"),
74 AlertDescription::BadRecordMac => write!(f, "BadRecordMac"),
75 AlertDescription::DecryptionFailed => write!(f, "DecryptionFailed"),
76 AlertDescription::RecordOverflow => write!(f, "RecordOverflow"),
77 AlertDescription::DecompressionFailure => write!(f, "DecompressionFailure"),
78 AlertDescription::HandshakeFailure => write!(f, "HandshakeFailure"),
79 AlertDescription::NoCertificate => write!(f, "NoCertificate"),
80 AlertDescription::BadCertificate => write!(f, "BadCertificate"),
81 AlertDescription::UnsupportedCertificate => write!(f, "UnsupportedCertificate"),
82 AlertDescription::CertificateRevoked => write!(f, "CertificateRevoked"),
83 AlertDescription::CertificateExpired => write!(f, "CertificateExpired"),
84 AlertDescription::CertificateUnknown => write!(f, "CertificateUnknown"),
85 AlertDescription::IllegalParameter => write!(f, "IllegalParameter"),
86 AlertDescription::UnknownCa => write!(f, "UnknownCA"),
87 AlertDescription::AccessDenied => write!(f, "AccessDenied"),
88 AlertDescription::DecodeError => write!(f, "DecodeError"),
89 AlertDescription::DecryptError => write!(f, "DecryptError"),
90 AlertDescription::ExportRestriction => write!(f, "ExportRestriction"),
91 AlertDescription::ProtocolVersion => write!(f, "ProtocolVersion"),
92 AlertDescription::InsufficientSecurity => write!(f, "InsufficientSecurity"),
93 AlertDescription::InternalError => write!(f, "InternalError"),
94 AlertDescription::UserCanceled => write!(f, "UserCanceled"),
95 AlertDescription::NoRenegotiation => write!(f, "NoRenegotiation"),
96 AlertDescription::UnsupportedExtension => write!(f, "UnsupportedExtension"),
97 AlertDescription::UnknownPskIdentity => write!(f, "UnknownPskIdentity"),
98 _ => write!(f, "Invalid alert description"),
99 }
100 }
101}
102
103impl From<u8> for AlertDescription {
104 fn from(val: u8) -> Self {
105 match val {
106 0 => AlertDescription::CloseNotify,
107 10 => AlertDescription::UnexpectedMessage,
108 20 => AlertDescription::BadRecordMac,
109 21 => AlertDescription::DecryptionFailed,
110 22 => AlertDescription::RecordOverflow,
111 30 => AlertDescription::DecompressionFailure,
112 40 => AlertDescription::HandshakeFailure,
113 41 => AlertDescription::NoCertificate,
114 42 => AlertDescription::BadCertificate,
115 43 => AlertDescription::UnsupportedCertificate,
116 44 => AlertDescription::CertificateRevoked,
117 45 => AlertDescription::CertificateExpired,
118 46 => AlertDescription::CertificateUnknown,
119 47 => AlertDescription::IllegalParameter,
120 48 => AlertDescription::UnknownCa,
121 49 => AlertDescription::AccessDenied,
122 50 => AlertDescription::DecodeError,
123 51 => AlertDescription::DecryptError,
124 60 => AlertDescription::ExportRestriction,
125 70 => AlertDescription::ProtocolVersion,
126 71 => AlertDescription::InsufficientSecurity,
127 80 => AlertDescription::InternalError,
128 90 => AlertDescription::UserCanceled,
129 100 => AlertDescription::NoRenegotiation,
130 110 => AlertDescription::UnsupportedExtension,
131 115 => AlertDescription::UnknownPskIdentity,
132 _ => AlertDescription::Invalid,
133 }
134 }
135}
136
137#[derive(Copy, Clone, PartialEq, Debug)]
152pub struct Alert {
153 pub(crate) alert_level: AlertLevel,
154 pub(crate) alert_description: AlertDescription,
155}
156
157impl fmt::Display for Alert {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 write!(f, "Alert {}: {}", self.alert_level, self.alert_description)
160 }
161}
162
163impl Alert {
164 pub fn content_type(&self) -> ContentType {
165 ContentType::Alert
166 }
167
168 pub fn size(&self) -> usize {
169 2
170 }
171
172 pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
173 writer.write_u8(self.alert_level as u8)?;
174 writer.write_u8(self.alert_description as u8)?;
175
176 Ok(writer.flush()?)
177 }
178
179 pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
180 let alert_level = reader.read_u8()?.into();
181 let alert_description = reader.read_u8()?.into();
182
183 Ok(Alert {
184 alert_level,
185 alert_description,
186 })
187 }
188}