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}