xref: /webrtc/dtls/src/alert/mod.rs (revision ffe74184)
1 #[cfg(test)]
2 mod alert_test;
3 
4 use super::content::*;
5 use crate::error::Result;
6 
7 use byteorder::{ReadBytesExt, WriteBytesExt};
8 use std::fmt;
9 use std::io::{Read, Write};
10 
11 #[derive(Copy, Clone, PartialEq, Debug)]
12 pub(crate) enum AlertLevel {
13     Warning = 1,
14     Fatal = 2,
15     Invalid,
16 }
17 
18 impl fmt::Display for AlertLevel {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result19     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 
28 impl From<u8> for AlertLevel {
from(val: u8) -> Self29     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)]
39 pub(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     Invalid,
66 }
67 
68 impl fmt::Display for AlertDescription {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result69     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70         match *self {
71             AlertDescription::CloseNotify => write!(f, "CloseNotify"),
72             AlertDescription::UnexpectedMessage => write!(f, "UnexpectedMessage"),
73             AlertDescription::BadRecordMac => write!(f, "BadRecordMac"),
74             AlertDescription::DecryptionFailed => write!(f, "DecryptionFailed"),
75             AlertDescription::RecordOverflow => write!(f, "RecordOverflow"),
76             AlertDescription::DecompressionFailure => write!(f, "DecompressionFailure"),
77             AlertDescription::HandshakeFailure => write!(f, "HandshakeFailure"),
78             AlertDescription::NoCertificate => write!(f, "NoCertificate"),
79             AlertDescription::BadCertificate => write!(f, "BadCertificate"),
80             AlertDescription::UnsupportedCertificate => write!(f, "UnsupportedCertificate"),
81             AlertDescription::CertificateRevoked => write!(f, "CertificateRevoked"),
82             AlertDescription::CertificateExpired => write!(f, "CertificateExpired"),
83             AlertDescription::CertificateUnknown => write!(f, "CertificateUnknown"),
84             AlertDescription::IllegalParameter => write!(f, "IllegalParameter"),
85             AlertDescription::UnknownCa => write!(f, "UnknownCA"),
86             AlertDescription::AccessDenied => write!(f, "AccessDenied"),
87             AlertDescription::DecodeError => write!(f, "DecodeError"),
88             AlertDescription::DecryptError => write!(f, "DecryptError"),
89             AlertDescription::ExportRestriction => write!(f, "ExportRestriction"),
90             AlertDescription::ProtocolVersion => write!(f, "ProtocolVersion"),
91             AlertDescription::InsufficientSecurity => write!(f, "InsufficientSecurity"),
92             AlertDescription::InternalError => write!(f, "InternalError"),
93             AlertDescription::UserCanceled => write!(f, "UserCanceled"),
94             AlertDescription::NoRenegotiation => write!(f, "NoRenegotiation"),
95             AlertDescription::UnsupportedExtension => write!(f, "UnsupportedExtension"),
96             _ => write!(f, "Invalid alert description"),
97         }
98     }
99 }
100 
101 impl From<u8> for AlertDescription {
from(val: u8) -> Self102     fn from(val: u8) -> Self {
103         match val {
104             0 => AlertDescription::CloseNotify,
105             10 => AlertDescription::UnexpectedMessage,
106             20 => AlertDescription::BadRecordMac,
107             21 => AlertDescription::DecryptionFailed,
108             22 => AlertDescription::RecordOverflow,
109             30 => AlertDescription::DecompressionFailure,
110             40 => AlertDescription::HandshakeFailure,
111             41 => AlertDescription::NoCertificate,
112             42 => AlertDescription::BadCertificate,
113             43 => AlertDescription::UnsupportedCertificate,
114             44 => AlertDescription::CertificateRevoked,
115             45 => AlertDescription::CertificateExpired,
116             46 => AlertDescription::CertificateUnknown,
117             47 => AlertDescription::IllegalParameter,
118             48 => AlertDescription::UnknownCa,
119             49 => AlertDescription::AccessDenied,
120             50 => AlertDescription::DecodeError,
121             51 => AlertDescription::DecryptError,
122             60 => AlertDescription::ExportRestriction,
123             70 => AlertDescription::ProtocolVersion,
124             71 => AlertDescription::InsufficientSecurity,
125             80 => AlertDescription::InternalError,
126             90 => AlertDescription::UserCanceled,
127             100 => AlertDescription::NoRenegotiation,
128             110 => AlertDescription::UnsupportedExtension,
129             _ => AlertDescription::Invalid,
130         }
131     }
132 }
133 
134 // One of the content types supported by the TLS record layer is the
135 // alert type.  Alert messages convey the severity of the message
136 // (warning or fatal) and a description of the alert.  Alert messages
137 // with a level of fatal result in the immediate termination of the
138 // connection.  In this case, other connections corresponding to the
139 // session may continue, but the session identifier MUST be invalidated,
140 // preventing the failed session from being used to establish new
141 // connections.  Like other messages, alert messages are encrypted and
142 // compressed, as specified by the current connection state.
143 // https://tools.ietf.org/html/rfc5246#section-7.2
144 #[derive(Copy, Clone, PartialEq, Debug)]
145 pub struct Alert {
146     pub(crate) alert_level: AlertLevel,
147     pub(crate) alert_description: AlertDescription,
148 }
149 
150 impl fmt::Display for Alert {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result151     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152         write!(f, "Alert {}: {}", self.alert_level, self.alert_description)
153     }
154 }
155 
156 impl Alert {
content_type(&self) -> ContentType157     pub fn content_type(&self) -> ContentType {
158         ContentType::Alert
159     }
160 
size(&self) -> usize161     pub fn size(&self) -> usize {
162         2
163     }
164 
marshal<W: Write>(&self, writer: &mut W) -> Result<()>165     pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
166         writer.write_u8(self.alert_level as u8)?;
167         writer.write_u8(self.alert_description as u8)?;
168 
169         Ok(writer.flush()?)
170     }
171 
unmarshal<R: Read>(reader: &mut R) -> Result<Self>172     pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
173         let alert_level = reader.read_u8()?.into();
174         let alert_description = reader.read_u8()?.into();
175 
176         Ok(Alert {
177             alert_level,
178             alert_description,
179         })
180     }
181 }
182