turn_server/stun/
message.rs

1use bytes::{BufMut, BytesMut};
2
3use std::convert::TryFrom;
4
5use super::{
6    Attributes, StunError,
7    attribute::{AttrKind, Attribute, MessageIntegrity},
8    method::StunMethod,
9    util,
10};
11
12const ZOER_BUF: [u8; 10] = [0u8; 10];
13const COOKIE: [u8; 4] = 0x2112A442u32.to_be_bytes();
14
15/// (username, password, realm)
16type Digest = [u8; 16];
17
18pub struct MessageEncoder<'a> {
19    pub token: &'a [u8],
20    pub bytes: &'a mut BytesMut,
21}
22
23impl<'a, 'b> MessageEncoder<'a> {
24    pub fn new(method: StunMethod, token: &'a [u8; 12], bytes: &'a mut BytesMut) -> Self {
25        unsafe { bytes.set_len(0) }
26        bytes.put_u16(method.into());
27        bytes.put_u16(0);
28        bytes.put(&COOKIE[..]);
29        bytes.put(token.as_slice());
30        Self { bytes, token }
31    }
32
33    /// rely on old message to create new message.
34    ///
35    /// # Test
36    ///
37    /// ```
38    /// use bytes::BytesMut;
39    /// use std::convert::TryFrom;
40    /// use turn_server::stun::method::{
41    ///     StunMethod as Method, StunMethodKind as Kind,
42    /// };
43    /// use turn_server::stun::*;
44    ///
45    /// let buffer = [
46    ///     0x00u8, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49,
47    ///     0x42, 0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
48    /// ];
49    ///
50    /// let mut attributes = Attributes::default();
51    /// let mut buf = BytesMut::new();
52    /// let old = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
53    /// MessageEncoder::extend(Method::Binding(Kind::Request), &old, &mut buf);
54    /// assert_eq!(&buf[..], &buffer[..]);
55    /// ```
56    pub fn extend(method: StunMethod, reader: &MessageRef<'a>, bytes: &'a mut BytesMut) -> Self {
57        let token = reader.token();
58
59        unsafe { bytes.set_len(0) }
60        bytes.put_u16(method.into());
61        bytes.put_u16(0);
62        bytes.put(&COOKIE[..]);
63        bytes.put(token);
64        Self { bytes, token }
65    }
66
67    /// append attribute.
68    ///
69    /// append attribute to message attribute list.
70    ///
71    /// # Test
72    ///
73    /// ```
74    /// use bytes::BytesMut;
75    /// use std::convert::TryFrom;
76    /// use turn_server::stun::attribute::UserName;
77    /// use turn_server::stun::method::{
78    ///     StunMethod as Method, StunMethodKind as Kind,
79    /// };
80    /// use turn_server::stun::*;
81    ///
82    /// let buffer = [
83    ///     0x00u8, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49,
84    ///     0x42, 0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
85    /// ];
86    ///
87    /// let new_buf = [
88    ///     0x00u8, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49,
89    ///     0x42, 0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b, 0x00, 0x06, 0x00,
90    ///     0x05, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x00, 0x00, 0x00,
91    /// ];
92    ///
93    /// let mut buf = BytesMut::new();
94    /// let mut attributes = Attributes::default();
95    /// let old = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
96    /// let mut message =
97    ///     MessageEncoder::extend(Method::Binding(Kind::Request), &old, &mut buf);
98    ///
99    /// message.append::<UserName>("panda");
100    /// assert_eq!(&new_buf[..], &buf[..]);
101    /// ```
102    pub fn append<'c, T: Attribute<'c>>(&'c mut self, value: T::Item) {
103        self.bytes.put_u16(T::KIND as u16);
104
105        // record the current position,
106        // and then advance the internal cursor 2 bytes,
107        // here is to reserve the position.
108        let os = self.bytes.len();
109        unsafe { self.bytes.advance_mut(2) }
110        T::encode(value, self.bytes, self.token);
111
112        // compute write index,
113        // back to source index write size.
114        let size = self.bytes.len() - os - 2;
115        let size_buf = (size as u16).to_be_bytes();
116        self.bytes[os] = size_buf[0];
117        self.bytes[os + 1] = size_buf[1];
118
119        // if you need to padding,
120        // padding in the zero bytes.
121        let psize = util::pad_size(size);
122        if psize > 0 {
123            self.bytes.put(&ZOER_BUF[0..psize]);
124        }
125    }
126
127    /// try decoder bytes as message.
128    ///
129    /// # Test
130    ///
131    /// ```
132    /// use bytes::BytesMut;
133    /// use std::convert::TryFrom;
134    /// use turn_server::stun::method::{
135    ///     StunMethod as Method, StunMethodKind as Kind,
136    /// };
137    /// use turn_server::stun::*;
138    ///
139    /// let buffer = [
140    ///     0x00u8, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49,
141    ///     0x42, 0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
142    /// ];
143    ///
144    /// let result = [
145    ///     0, 1, 0, 32, 33, 18, 164, 66, 114, 109, 73, 66, 114, 82, 100, 72, 87,
146    ///     98, 75, 43, 0, 8, 0, 20, 69, 14, 110, 68, 82, 30, 232, 222, 44, 240,
147    ///     250, 182, 156, 92, 25, 23, 152, 198, 217, 222, 128, 40, 0, 4, 74, 165,
148    ///     171, 86,
149    /// ];
150    ///
151    /// let mut attributes = Attributes::default();
152    /// let mut buf = BytesMut::with_capacity(1280);
153    /// let old = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
154    /// let mut message =
155    ///     MessageEncoder::extend(Method::Binding(Kind::Request), &old, &mut buf);
156    ///
157    /// message
158    ///     .flush(Some(&util::long_term_credential_digest(
159    ///         "panda",
160    ///         "panda",
161    ///         "raspberry",
162    ///     )))
163    ///     .unwrap();
164    /// assert_eq!(&buf[..], &result);
165    /// ```
166    pub fn flush(&mut self, digest: Option<&Digest>) -> Result<(), StunError> {
167        // write attribute list size.
168        self.set_len(self.bytes.len() - 20);
169
170        // if need message integrity?
171        if let Some(a) = digest {
172            self.integrity(a)?;
173        }
174
175        Ok(())
176    }
177
178    /// append MessageIntegrity attribute.
179    ///
180    /// add the `MessageIntegrity` attribute to the stun message
181    /// and serialize the message into a buffer.
182    ///
183    /// # Test
184    ///
185    /// ```
186    /// use bytes::BytesMut;
187    /// use std::convert::TryFrom;
188    /// use turn_server::stun::method::{
189    ///     StunMethod as Method, StunMethodKind as Kind,
190    /// };
191    /// use turn_server::stun::*;
192    ///
193    /// let buffer = [
194    ///     0x00u8, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49,
195    ///     0x42, 0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
196    /// ];
197    ///
198    /// let result = [
199    ///     0, 1, 0, 32, 33, 18, 164, 66, 114, 109, 73, 66, 114, 82, 100, 72, 87,
200    ///     98, 75, 43, 0, 8, 0, 20, 69, 14, 110, 68, 82, 30, 232, 222, 44, 240,
201    ///     250, 182, 156, 92, 25, 23, 152, 198, 217, 222, 128, 40, 0, 4, 74, 165,
202    ///     171, 86,
203    /// ];
204    ///
205    /// let mut attributes = Attributes::default();
206    /// let mut buf = BytesMut::from(&buffer[..]);
207    /// let old = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
208    /// let mut message =
209    ///     MessageEncoder::extend(Method::Binding(Kind::Request), &old, &mut buf);
210    ///
211    /// message
212    ///     .flush(Some(&util::long_term_credential_digest(
213    ///         "panda",
214    ///         "panda",
215    ///         "raspberry",
216    ///     )))
217    ///     .unwrap();
218    /// assert_eq!(&buf[..], &result);
219    /// ```
220    fn integrity(&mut self, digest: &Digest) -> Result<(), StunError> {
221        assert!(self.bytes.len() >= 20);
222        let len = self.bytes.len();
223
224        // compute new size,
225        // new size include the MessageIntegrity attribute size.
226        self.set_len(len + 4);
227
228        // write MessageIntegrity attribute.
229        let hmac_output = util::hmac_sha1(digest, &[self.bytes])?.into_bytes();
230        self.bytes.put_u16(AttrKind::MessageIntegrity as u16);
231        self.bytes.put_u16(20);
232        self.bytes.put(hmac_output.as_slice());
233
234        // compute new size,
235        // new size include the Fingerprint attribute size.
236        self.set_len(len + 4 + 8);
237
238        // CRC Fingerprint
239        let fingerprint = util::fingerprint(self.bytes);
240        self.bytes.put_u16(AttrKind::Fingerprint as u16);
241        self.bytes.put_u16(4);
242        self.bytes.put_u32(fingerprint);
243
244        Ok(())
245    }
246
247    // set stun message header size.
248    fn set_len(&mut self, len: usize) {
249        self.bytes[2..4].copy_from_slice((len as u16).to_be_bytes().as_slice());
250    }
251}
252
253pub struct MessageDecoder;
254
255impl MessageDecoder {
256    /// # Test
257    ///
258    /// ```
259    /// use std::convert::TryFrom;
260    /// use turn_server::stun::attribute::*;
261    /// use turn_server::stun::method::*;
262    /// use turn_server::stun::*;
263    ///
264    /// let buffer: [u8; 20] = [
265    ///     0x00, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49, 0x42,
266    ///     0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
267    /// ];
268    ///
269    /// let mut attributes = Attributes::default();
270    /// let message = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
271    /// assert_eq!(
272    ///     message.method(),
273    ///     StunMethod::Binding(StunMethodKind::Request)
274    /// );
275    /// assert!(message.get::<UserName>().is_none());
276    /// ```
277    pub fn decode<'a>(bytes: &'a [u8], attributes: &'a mut Attributes) -> Result<MessageRef<'a>, StunError> {
278        if bytes.len() < 20 {
279            return Err(StunError::InvalidInput);
280        }
281
282        let count_size = bytes.len();
283        let mut find_integrity = false;
284        let mut payload_size = 0;
285
286        // message type
287        // message size
288        // check fixed magic cookie
289        // check if the message size is overflow
290        let method = StunMethod::try_from(u16::from_be_bytes(bytes[..2].try_into()?))?;
291        let size = u16::from_be_bytes(bytes[2..4].try_into()?) as usize + 20;
292        if bytes[4..8] != COOKIE[..] {
293            return Err(StunError::NotFoundCookie);
294        }
295
296        if count_size < size {
297            return Err(StunError::InvalidInput);
298        }
299
300        let mut offset = 20;
301        loop {
302            // if the buf length is not long enough to continue,
303            // jump out of the loop.
304            if count_size - offset < 4 {
305                break;
306            }
307
308            // get attribute type
309            let key = u16::from_be_bytes([bytes[offset], bytes[offset + 1]]);
310
311            // whether the MessageIntegrity attribute has been found,
312            // if found, record the current offset position.
313            if !find_integrity {
314                payload_size = offset as u16;
315            }
316
317            // check whether the current attribute is MessageIntegrity,
318            // if it is, mark this attribute has been found.
319            if key == AttrKind::MessageIntegrity as u16 {
320                find_integrity = true;
321            }
322
323            // get attribute size
324            let size = u16::from_be_bytes([bytes[offset + 2], bytes[offset + 3]]) as usize;
325
326            // check if the attribute length has overflowed.
327            offset += 4;
328            if count_size - offset < size {
329                break;
330            }
331
332            // body range.
333            let range = offset..(offset + size);
334
335            // if there are padding bytes,
336            // skip padding size.
337            if size > 0 {
338                offset += size;
339                offset += util::pad_size(size);
340            }
341
342            // skip the attributes that are not supported.
343            let attrkind = match AttrKind::try_from(key) {
344                Err(_) => continue,
345                Ok(a) => a,
346            };
347
348            // get attribute body
349            // insert attribute to attributes list.
350            attributes.append(attrkind, range);
351        }
352
353        Ok(MessageRef {
354            size: payload_size,
355            attributes,
356            method,
357            bytes,
358        })
359    }
360
361    /// # Test
362    ///
363    /// ```
364    /// use turn_server::stun::*;
365    ///
366    /// let buffer: [u8; 20] = [
367    ///     0x00, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49, 0x42,
368    ///     0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
369    /// ];
370    ///
371    /// let size = MessageDecoder::message_size(&buffer[..]).unwrap();
372    /// assert_eq!(size, 20);
373    /// ```
374    pub fn message_size(buf: &[u8]) -> Result<usize, StunError> {
375        if buf[0] >> 6 != 0 || buf.len() < 20 {
376            return Err(StunError::InvalidInput);
377        }
378
379        Ok((u16::from_be_bytes(buf[2..4].try_into()?) + 20) as usize)
380    }
381}
382
383#[derive(Debug)]
384pub struct MessageRef<'a> {
385    /// message method.
386    method: StunMethod,
387    /// message source bytes.
388    bytes: &'a [u8],
389    /// message payload size.
390    size: u16,
391    // message attribute list.
392    attributes: &'a Attributes,
393}
394
395impl<'a> MessageRef<'a> {
396    /// message method.
397    #[inline]
398    pub fn method(&self) -> StunMethod {
399        self.method
400    }
401
402    /// message transaction id.
403    #[inline]
404    pub fn token(&self) -> &'a [u8] {
405        &self.bytes[8..20]
406    }
407
408    /// get attribute.
409    ///
410    /// get attribute from message attribute list.
411    ///
412    /// # Test
413    ///
414    /// ```
415    /// use std::convert::TryFrom;
416    /// use turn_server::stun::attribute::*;
417    /// use turn_server::stun::*;
418    ///
419    /// let buffer = [
420    ///     0x00u8, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49,
421    ///     0x42, 0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
422    /// ];
423    ///
424    /// let mut attributes = Attributes::default();
425    /// let message = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
426    /// assert!(message.get::<UserName>().is_none());
427    /// ```
428    pub fn get<T: Attribute<'a>>(&self) -> Option<T::Item> {
429        let range = self.attributes.get(&T::KIND)?;
430        T::decode(&self.bytes[range.clone()], self.token()).ok()
431    }
432
433    /// Gets all the values of an attribute from a list.
434    ///
435    /// Normally a stun message can have multiple attributes with the same name,
436    /// and this function will all the values of the current attribute.
437    ///
438    /// # Test
439    ///
440    /// ```
441    /// use std::convert::TryFrom;
442    /// use turn_server::stun::attribute::*;
443    /// use turn_server::stun::*;
444    ///
445    /// let buffer = [
446    ///     0x00u8, 0x01, 0x00, 0x00, 0x21, 0x12, 0xa4, 0x42, 0x72, 0x6d, 0x49,
447    ///     0x42, 0x72, 0x52, 0x64, 0x48, 0x57, 0x62, 0x4b, 0x2b,
448    /// ];
449    ///
450    /// let mut attributes = Attributes::default();
451    /// let message = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
452    ///
453    /// assert_eq!(message.get_all::<UserName>().next(), None);
454    /// ```
455    pub fn get_all<T: Attribute<'a>>(&self) -> impl Iterator<Item = T::Item> {
456        self.attributes
457            .get_all(&T::KIND)
458            .map(|it| T::decode(&self.bytes[it.clone()], self.token()))
459            .filter(|it| it.is_ok())
460            .map(|it| it.unwrap())
461    }
462
463    /// check MessageRefIntegrity attribute.
464    ///
465    /// return whether the `MessageRefIntegrity` attribute
466    /// contained in the message can pass the check.
467    ///
468    /// # Test
469    ///
470    /// ```
471    /// use std::convert::TryFrom;
472    /// use turn_server::stun::*;
473    ///
474    /// let buffer = [
475    ///     0x00u8, 0x03, 0x00, 0x50, 0x21, 0x12, 0xa4, 0x42, 0x64, 0x4f, 0x5a,
476    ///     0x78, 0x6a, 0x56, 0x33, 0x62, 0x4b, 0x52, 0x33, 0x31, 0x00, 0x19, 0x00,
477    ///     0x04, 0x11, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x70, 0x61, 0x6e,
478    ///     0x64, 0x61, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x09, 0x72, 0x61, 0x73,
479    ///     0x70, 0x62, 0x65, 0x72, 0x72, 0x79, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00,
480    ///     0x10, 0x31, 0x63, 0x31, 0x33, 0x64, 0x32, 0x62, 0x32, 0x34, 0x35, 0x62,
481    ///     0x33, 0x61, 0x37, 0x33, 0x34, 0x00, 0x08, 0x00, 0x14, 0xd6, 0x78, 0x26,
482    ///     0x99, 0x0e, 0x15, 0x56, 0x15, 0xe5, 0xf4, 0x24, 0x74, 0xe2, 0x3c, 0x26,
483    ///     0xc5, 0xb1, 0x03, 0xb2, 0x6d,
484    /// ];
485    ///
486    /// let mut attributes = Attributes::default();
487    /// let message = MessageDecoder::decode(&buffer[..], &mut attributes).unwrap();
488    /// let result = message
489    ///     .integrity(&util::long_term_credential_digest(
490    ///         "panda",
491    ///         "panda",
492    ///         "raspberry",
493    ///     ))
494    ///     .is_ok();
495    /// assert!(result);
496    /// ```
497    pub fn integrity(&self, digest: &Digest) -> Result<(), StunError> {
498        if self.bytes.is_empty() || self.size < 20 {
499            return Err(StunError::InvalidInput);
500        }
501
502        // unwrap MessageIntegrity attribute,
503        // an error occurs if not found.
504        let integrity = self.get::<MessageIntegrity>().ok_or(StunError::NotFoundIntegrity)?;
505
506        // create multiple submit.
507        let size_buf = (self.size + 4).to_be_bytes();
508        let body = [&self.bytes[0..2], &size_buf, &self.bytes[4..self.size as usize]];
509
510        // digest the message buffer.
511        let hmac_output = util::hmac_sha1(digest, &body)?.into_bytes();
512        let hmac_buf = hmac_output.as_slice();
513
514        // Compare local and original attribute.
515        if integrity != hmac_buf {
516            return Err(StunError::IntegrityFailed);
517        }
518
519        Ok(())
520    }
521}