Skip to main content

rtc_dtls/alert/
mod.rs

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// One of the content types supported by the TLS record layer is the
138// alert type.  Alert messages convey the severity of the message
139// (warning or fatal) and a description of the alert.  Alert messages
140// with a level of fatal result in the immediate termination of the
141// connection.  In this case, other connections corresponding to the
142// session may continue, but the session identifier MUST be invalidated,
143// preventing the failed session from being used to establish new
144// connections.  Like other messages, alert messages are encrypted and
145// compressed, as specified by the current connection state.
146/// ## Specifications
147///
148/// * [RFC 5246 §7.2]
149///
150/// [RFC 5246 §7.2]: https://tools.ietf.org/html/rfc5246#section-7.2
151#[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}