webrtc_dtls/alert/
mod.rs

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