faster_stun/lib.rs
1//! ## Session Traversal Utilities for NAT (STUN)
2//!
3//! [RFC8445]: https://tools.ietf.org/html/rfc8445
4//! [RFC5626]: https://tools.ietf.org/html/rfc5626
5//! [Section 13]: https://tools.ietf.org/html/rfc8489#section-13
6//!
7//! ### STUN Message Structure
8//!
9//! ```text
10//! 0 1 2 3
11//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
12//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13//! |0 0| STUN Message Type | Message Length |
14//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15//! | Magic Cookie |
16//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17//! | |
18//! | Transaction ID (96 bits) |
19//! | |
20//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21//! ```
22//!
23//! ### STUN Attributes
24//!
25//! ```text
26//! 0 1 2 3
27//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
28//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29//! | Type | Length |
30//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31//! | Value (variable) ....
32//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33//! ```
34//!
35//! STUN is intended to be used in the context of one or more NAT
36//! traversal solutions. These solutions are known as "STUN Usages".
37//! Each usage describes how STUN is utilized to achieve the NAT
38//! traversal solution. Typically, a usage indicates when STUN messages
39//! get sent, which optional attributes to include, what server is used,
40//! and what authentication mechanism is to be used. Interactive
41//! Connectivity Establishment (ICE) [RFC8445] is one usage of STUN.
42//! SIP Outbound [RFC5626] is another usage of STUN. In some cases,
43//! a usage will require extensions to STUN. A STUN extension can be
44//! in the form of new methods, attributes, or error response codes.
45//! More information on STUN Usages can be found in [Section 13].
46
47pub mod attribute;
48pub mod channel;
49pub mod message;
50pub mod util;
51
52use std::{error, fmt};
53
54pub use channel::ChannelData;
55pub use message::*;
56
57#[derive(Debug)]
58pub enum StunError {
59 InvalidInput,
60 UnsupportedIpFamily,
61 ShaFailed,
62 NotIntegrity,
63 IntegrityFailed,
64 NotCookie,
65 UnknownMethod,
66 FatalError,
67 Utf8Error,
68}
69
70impl error::Error for StunError {}
71
72impl fmt::Display for StunError {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(
75 f,
76 "{}",
77 match self {
78 Self::InvalidInput => "InvalidInput",
79 Self::UnsupportedIpFamily => "UnsupportedIpFamily",
80 Self::ShaFailed => "ShaFailed",
81 Self::NotIntegrity => "NotIntegrity",
82 Self::IntegrityFailed => "IntegrityFailed",
83 Self::NotCookie => "NotCookie",
84 Self::UnknownMethod => "UnknownMethod",
85 Self::FatalError => "FatalError",
86 Self::Utf8Error => "Utf8Error",
87 }
88 )
89 }
90}
91
92/// STUN Methods Registry
93///
94/// [RFC5389]: https://datatracker.ietf.org/doc/html/rfc5389
95/// [RFC8489]: https://datatracker.ietf.org/doc/html/rfc8489
96/// [RFC8126]: https://datatracker.ietf.org/doc/html/rfc8126
97/// [Section 5]: https://datatracker.ietf.org/doc/html/rfc8489#section-5
98///
99/// A STUN method is a hex number in the range 0x000-0x0FF. The encoding
100/// of a STUN method into a STUN message is described in [Section 5].
101///
102/// STUN methods in the range 0x000-0x07F are assigned by IETF Review
103/// [RFC8126]. STUN methods in the range 0x080-0x0FF are assigned by
104/// Expert Review [RFC8126]. The responsibility of the expert is to
105/// verify that the selected codepoint(s) is not in use and that the
106/// request is not for an abnormally large number of codepoints.
107/// Technical review of the extension itself is outside the scope of the
108/// designated expert responsibility.
109///
110/// IANA has updated the name for method 0x002 as described below as well
111/// as updated the reference from [RFC5389] to [RFC8489] for the following
112/// STUN methods:
113///
114/// 0x000: Reserved
115/// 0x001: Binding
116/// 0x002: Reserved; was SharedSecret prior to [RFC5389]
117/// 0x003: Allocate
118/// 0x004: Refresh
119/// 0x006: Send
120/// 0x007: Data
121/// 0x008: CreatePermission
122/// 0x009: ChannelBind
123#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
124pub enum Kind {
125 Request,
126 Response,
127 Error,
128}
129
130#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
131pub enum Method {
132 Binding(Kind),
133 Allocate(Kind),
134 CreatePermission(Kind),
135 ChannelBind(Kind),
136 Refresh(Kind),
137 SendIndication,
138 DataIndication,
139}
140
141impl TryFrom<u16> for Method {
142 type Error = StunError;
143
144 /// # Unit Test
145 ///
146 /// ```
147 /// use faster_stun::*;
148 /// use std::convert::TryFrom;
149 ///
150 /// assert_eq!(
151 /// Method::try_from(0x0001).unwrap(),
152 /// Method::Binding(Kind::Request)
153 /// );
154 /// assert_eq!(
155 /// Method::try_from(0x0101).unwrap(),
156 /// Method::Binding(Kind::Response)
157 /// );
158 /// assert_eq!(
159 /// Method::try_from(0x0111).unwrap(),
160 /// Method::Binding(Kind::Error)
161 /// );
162 /// assert_eq!(
163 /// Method::try_from(0x0003).unwrap(),
164 /// Method::Allocate(Kind::Request)
165 /// );
166 /// assert_eq!(
167 /// Method::try_from(0x0103).unwrap(),
168 /// Method::Allocate(Kind::Response)
169 /// );
170 /// assert_eq!(
171 /// Method::try_from(0x0113).unwrap(),
172 /// Method::Allocate(Kind::Error)
173 /// );
174 /// assert_eq!(
175 /// Method::try_from(0x0008).unwrap(),
176 /// Method::CreatePermission(Kind::Request)
177 /// );
178 /// assert_eq!(
179 /// Method::try_from(0x0108).unwrap(),
180 /// Method::CreatePermission(Kind::Response)
181 /// );
182 /// assert_eq!(
183 /// Method::try_from(0x0118).unwrap(),
184 /// Method::CreatePermission(Kind::Error)
185 /// );
186 /// assert_eq!(
187 /// Method::try_from(0x0009).unwrap(),
188 /// Method::ChannelBind(Kind::Request)
189 /// );
190 /// assert_eq!(
191 /// Method::try_from(0x0109).unwrap(),
192 /// Method::ChannelBind(Kind::Response)
193 /// );
194 /// assert_eq!(
195 /// Method::try_from(0x0119).unwrap(),
196 /// Method::ChannelBind(Kind::Error)
197 /// );
198 /// assert_eq!(
199 /// Method::try_from(0x0004).unwrap(),
200 /// Method::Refresh(Kind::Request)
201 /// );
202 /// assert_eq!(
203 /// Method::try_from(0x0104).unwrap(),
204 /// Method::Refresh(Kind::Response)
205 /// );
206 /// assert_eq!(
207 /// Method::try_from(0x0114).unwrap(),
208 /// Method::Refresh(Kind::Error)
209 /// );
210 /// assert_eq!(Method::try_from(0x0016).unwrap(), Method::SendIndication);
211 /// assert_eq!(Method::try_from(0x0017).unwrap(), Method::DataIndication);
212 /// ```
213 fn try_from(value: u16) -> Result<Self, Self::Error> {
214 Ok(match value {
215 0x0001 => Self::Binding(Kind::Request),
216 0x0101 => Self::Binding(Kind::Response),
217 0x0111 => Self::Binding(Kind::Error),
218 0x0003 => Self::Allocate(Kind::Request),
219 0x0103 => Self::Allocate(Kind::Response),
220 0x0113 => Self::Allocate(Kind::Error),
221 0x0008 => Self::CreatePermission(Kind::Request),
222 0x0108 => Self::CreatePermission(Kind::Response),
223 0x0118 => Self::CreatePermission(Kind::Error),
224 0x0009 => Self::ChannelBind(Kind::Request),
225 0x0109 => Self::ChannelBind(Kind::Response),
226 0x0119 => Self::ChannelBind(Kind::Error),
227 0x0004 => Self::Refresh(Kind::Request),
228 0x0104 => Self::Refresh(Kind::Response),
229 0x0114 => Self::Refresh(Kind::Error),
230 0x0016 => Self::SendIndication,
231 0x0017 => Self::DataIndication,
232 _ => return Err(StunError::UnknownMethod),
233 })
234 }
235}
236
237impl From<Method> for u16 {
238 /// # Unit Test
239 ///
240 /// ```
241 /// use faster_stun::*;
242 /// use std::convert::Into;
243 ///
244 /// assert_eq!(0x0001u16, Method::Binding(Kind::Request).into());
245 /// assert_eq!(0x0101u16, Method::Binding(Kind::Response).into());
246 /// assert_eq!(0x0111u16, Method::Binding(Kind::Error).into());
247 /// assert_eq!(0x0003u16, Method::Allocate(Kind::Request).into());
248 /// assert_eq!(0x0103u16, Method::Allocate(Kind::Response).into());
249 /// assert_eq!(0x0113u16, Method::Allocate(Kind::Error).into());
250 /// assert_eq!(0x0008u16, Method::CreatePermission(Kind::Request).into());
251 /// assert_eq!(0x0108u16, Method::CreatePermission(Kind::Response).into());
252 /// assert_eq!(0x0118u16, Method::CreatePermission(Kind::Error).into());
253 /// assert_eq!(0x0009u16, Method::ChannelBind(Kind::Request).into());
254 /// assert_eq!(0x0109u16, Method::ChannelBind(Kind::Response).into());
255 /// assert_eq!(0x0119u16, Method::ChannelBind(Kind::Error).into());
256 /// assert_eq!(0x0004u16, Method::Refresh(Kind::Request).into());
257 /// assert_eq!(0x0104u16, Method::Refresh(Kind::Response).into());
258 /// assert_eq!(0x0114u16, Method::Refresh(Kind::Error).into());
259 /// assert_eq!(0x0016u16, Method::SendIndication.into());
260 /// assert_eq!(0x0017u16, Method::DataIndication.into());
261 /// ```
262 fn from(val: Method) -> Self {
263 match val {
264 Method::Binding(Kind::Request) => 0x0001,
265 Method::Binding(Kind::Response) => 0x0101,
266 Method::Binding(Kind::Error) => 0x0111,
267 Method::Allocate(Kind::Request) => 0x0003,
268 Method::Allocate(Kind::Response) => 0x0103,
269 Method::Allocate(Kind::Error) => 0x0113,
270 Method::CreatePermission(Kind::Request) => 0x0008,
271 Method::CreatePermission(Kind::Response) => 0x0108,
272 Method::CreatePermission(Kind::Error) => 0x0118,
273 Method::ChannelBind(Kind::Request) => 0x0009,
274 Method::ChannelBind(Kind::Response) => 0x0109,
275 Method::ChannelBind(Kind::Error) => 0x0119,
276 Method::Refresh(Kind::Request) => 0x0004,
277 Method::Refresh(Kind::Response) => 0x0104,
278 Method::Refresh(Kind::Error) => 0x0114,
279 Method::SendIndication => 0x0016,
280 Method::DataIndication => 0x0017,
281 }
282 }
283}
284
285#[derive(Debug)]
286pub enum Payload<'a, 'b> {
287 Message(MessageReader<'a, 'b>),
288 ChannelData(ChannelData<'a>),
289}
290
291pub struct Decoder {
292 attrs: Vec<(attribute::AttrKind, &'static [u8])>,
293}
294
295impl Decoder {
296 pub fn new() -> Self {
297 Self {
298 attrs: Vec::with_capacity(10),
299 }
300 }
301
302 /// # Unit Test
303 ///
304 /// ```
305 /// use faster_stun::attribute::*;
306 /// use faster_stun::*;
307 ///
308 /// let buffer = [
309 /// 0x00, 0x01, 0x00, 0x4c, 0x21, 0x12, 0xa4, 0x42, 0x71, 0x66, 0x46, 0x31,
310 /// 0x2b, 0x59, 0x79, 0x65, 0x56, 0x69, 0x32, 0x72, 0x00, 0x06, 0x00, 0x09,
311 /// 0x55, 0x43, 0x74, 0x39, 0x3a, 0x56, 0x2f, 0x2b, 0x2f, 0x00, 0x00, 0x00,
312 /// 0xc0, 0x57, 0x00, 0x04, 0x00, 0x00, 0x03, 0xe7, 0x80, 0x29, 0x00, 0x08,
313 /// 0x22, 0x49, 0xda, 0x28, 0x2c, 0x6f, 0x2e, 0xdb, 0x00, 0x24, 0x00, 0x04,
314 /// 0x6e, 0x00, 0x28, 0xff, 0x00, 0x08, 0x00, 0x14, 0x19, 0x58, 0xda, 0x38,
315 /// 0xed, 0x1e, 0xdd, 0xc8, 0x6b, 0x8e, 0x22, 0x63, 0x3a, 0x22, 0x63, 0x97,
316 /// 0xcf, 0xf5, 0xde, 0x82, 0x80, 0x28, 0x00, 0x04, 0x56, 0xf7, 0xa3, 0xed,
317 /// ];
318 ///
319 /// let mut decoder = Decoder::new();
320 /// let payload = decoder.decode(&buffer).unwrap();
321 /// if let Payload::Message(reader) = payload {
322 /// assert!(reader.get::<UserName>().is_some())
323 /// }
324 /// ```
325 pub fn decode<'a>(&mut self, buf: &'a [u8]) -> Result<Payload<'a, '_>, StunError> {
326 assert!(buf.len() >= 4);
327 if !self.attrs.is_empty() {
328 self.attrs.clear();
329 }
330
331 let flag = buf[0] >> 6;
332 if flag > 3 {
333 return Err(StunError::InvalidInput);
334 }
335
336 Ok(if flag == 0 {
337 // attrs will not be used again after decode is used, so the
338 // reference is safe. Unsafe is used here to make the external life
339 // cycle declaration cleaner.
340 Payload::Message(MessageReader::decode(
341 unsafe { std::mem::transmute(buf) },
342 &mut self.attrs,
343 )?)
344 } else {
345 Payload::ChannelData(ChannelData::try_from(buf)?)
346 })
347 }
348
349 /// # Unit Test
350 ///
351 /// ```
352 /// use faster_stun::attribute::*;
353 /// use faster_stun::*;
354 ///
355 /// let buffer = [
356 /// 0x00, 0x01, 0x00, 0x4c, 0x21, 0x12, 0xa4, 0x42, 0x71, 0x66, 0x46, 0x31,
357 /// 0x2b, 0x59, 0x79, 0x65, 0x56, 0x69, 0x32, 0x72, 0x00, 0x06, 0x00, 0x09,
358 /// 0x55, 0x43, 0x74, 0x39, 0x3a, 0x56, 0x2f, 0x2b, 0x2f, 0x00, 0x00, 0x00,
359 /// 0xc0, 0x57, 0x00, 0x04, 0x00, 0x00, 0x03, 0xe7, 0x80, 0x29, 0x00, 0x08,
360 /// 0x22, 0x49, 0xda, 0x28, 0x2c, 0x6f, 0x2e, 0xdb, 0x00, 0x24, 0x00, 0x04,
361 /// 0x6e, 0x00, 0x28, 0xff, 0x00, 0x08, 0x00, 0x14, 0x19, 0x58, 0xda, 0x38,
362 /// 0xed, 0x1e, 0xdd, 0xc8, 0x6b, 0x8e, 0x22, 0x63, 0x3a, 0x22, 0x63, 0x97,
363 /// 0xcf, 0xf5, 0xde, 0x82, 0x80, 0x28, 0x00, 0x04, 0x56, 0xf7, 0xa3, 0xed,
364 /// ];
365 ///
366 /// let size = Decoder::message_size(&buffer, false).unwrap();
367 /// assert_eq!(size, 96);
368 /// ```
369 pub fn message_size(buf: &[u8], is_tcp: bool) -> Result<usize, StunError> {
370 let flag = buf[0] >> 6;
371 if flag > 3 {
372 return Err(StunError::InvalidInput);
373 }
374
375 Ok(if flag == 0 {
376 MessageReader::message_size(buf)?
377 } else {
378 ChannelData::message_size(buf, is_tcp)?
379 })
380 }
381}
382
383impl Default for Decoder {
384 fn default() -> Self {
385 Self::new()
386 }
387}