faster_stun/
message.rs

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