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}