1use crate::attributes::stun::{Fingerprint, MessageIntegrity, MessageIntegritySha256};
2use crate::attributes::{AsVerifiable, EncodeAttributeValue, Unknown};
3use crate::common::{check_buffer_boundaries, fill_padding_value, padding, DEFAULT_PADDING_VALUE};
4use crate::error::{
5 StunAttributeError, StunDecodeError, StunEncodeError, StunError, StunErrorLevel, StunErrorType,
6 StunMessageError,
7};
8use crate::raw::{
9 get_input_text, RawAttributes, RawMessage, ATTRIBUTE_HEADER_SIZE, MESSAGE_HEADER_SIZE,
10};
11use crate::registry::get_handler;
12use crate::types::MAGIC_COOKIE;
13use crate::{
14 AttributeType, Decode, Encode, MessageType, StunAttributeType, StunMessageBuilder,
15 TransactionId,
16};
17use crate::{HMACKey, StunAttribute, StunMessage};
18use byteorder::{BigEndian, ByteOrder};
19use fallible_iterator::{FallibleIterator, IntoFallibleIterator};
20use std::convert::{TryFrom, TryInto};
21
22#[derive(Debug, Default)]
24pub struct DecoderContextBuilder(DecoderContext);
25
26impl DecoderContextBuilder {
27 pub fn with_key(mut self, key: HMACKey) -> Self {
29 self.0.key = Some(key);
30 self
31 }
32
33 pub fn with_validation(mut self) -> Self {
35 self.0.validation = true;
36 self
37 }
38
39 pub fn with_unknown_data(mut self) -> Self {
43 self.0.unknown_data = true;
44 self
45 }
46
47 pub fn not_ignore(mut self) -> Self {
53 self.0.not_ignore = true;
54 self
55 }
56
57 pub fn build(self) -> DecoderContext {
59 self.0
60 }
61}
62
63#[derive(Debug, Default)]
64pub(crate) struct AttributeDecoderContext<'a> {
65 ctx: Option<DecoderContext>,
66 decoded_msg: &'a [u8],
67 raw_value: &'a [u8],
68}
69
70impl<'a> AttributeDecoderContext<'a> {
71 pub(crate) fn new(
72 ctx: Option<DecoderContext>,
73 decoded_msg: &'a [u8],
74 raw_value: &'a [u8],
75 ) -> Self {
76 Self {
77 ctx,
78 decoded_msg,
79 raw_value,
80 }
81 }
82 pub fn context(&self) -> Option<DecoderContext> {
83 self.ctx.clone()
84 }
85
86 pub fn decoded_message(&self) -> &[u8] {
87 self.decoded_msg
88 }
89
90 pub fn raw_value(&self) -> &[u8] {
91 self.raw_value
92 }
93}
94
95#[derive(Debug, Default, PartialEq, Eq, Clone)]
97pub struct DecoderContext {
98 key: Option<HMACKey>,
99 validation: bool,
100 unknown_data: bool,
101 not_ignore: bool,
102}
103
104impl DecoderContext {
105 pub fn key(&self) -> Option<&HMACKey> {
107 self.key.as_ref()
108 }
109
110 pub fn validate(&self) -> bool {
112 self.validation
113 }
114
115 pub fn with_unknown_data(&self) -> bool {
117 self.unknown_data
118 }
119}
120
121#[derive(Debug, Default)]
123pub struct MessageDecoderBuilder(MessageDecoder);
124impl MessageDecoderBuilder {
125 pub fn with_context(mut self, ctx: DecoderContext) -> Self {
127 self.0.ctx = Some(ctx);
128 self
129 }
130
131 pub fn build(self) -> MessageDecoder {
133 self.0
134 }
135}
136
137#[derive(Debug, Default, Clone)]
139pub struct MessageDecoder {
140 ctx: Option<DecoderContext>,
141}
142
143fn validate_attribute(
144 attr: &StunAttribute,
145 ctx: &Option<DecoderContext>,
146 buffer: &[u8],
147) -> Result<(), StunError> {
148 match ctx.as_ref() {
149 Some(ctx) => {
150 if ctx.validate() {
151 match attr.as_verifiable_ref() {
152 Some(verifiable) => {
153 let input = get_input_text(buffer, attr.attribute_type().as_u16())?;
154 verifiable.verify(&input, ctx).then_some(()).ok_or_else(|| {
155 StunError::new(
156 StunErrorType::ValidationFailed,
157 "Attribute validation failed",
158 )
159 })
160 }
161 None => Ok(()),
162 }
163 } else {
164 Ok(())
166 }
167 }
168 None => Ok(()),
169 }
170}
171
172#[derive(Debug, Default)]
173struct AttributeFilter {
174 message_integrity: bool,
175 message_integrity_sha256: bool,
176 fingerprint: bool,
177}
178
179fn ignore_attribute(f: &mut AttributeFilter, attr_type: AttributeType) -> bool {
180 if !f.message_integrity && attr_type == MessageIntegrity::get_type() {
181 if f.message_integrity_sha256 || f.fingerprint {
182 return true;
185 } else {
186 f.message_integrity = true;
187 return false;
188 }
189 }
190
191 if !f.message_integrity_sha256 && attr_type == MessageIntegritySha256::get_type() {
192 if f.fingerprint {
193 return true;
196 } else {
197 f.message_integrity_sha256 = true;
198 return false;
199 }
200 }
201
202 if !f.fingerprint && attr_type == Fingerprint::get_type() {
203 f.message_integrity_sha256 = true;
204 return false;
205 }
206
207 f.message_integrity || f.message_integrity_sha256 || f.fingerprint
210}
211
212impl MessageDecoder {
213 pub fn decode(&self, buffer: &[u8]) -> Result<(StunMessage, usize), StunDecodeError> {
220 let (raw_msg, size) = RawMessage::decode(buffer)
221 .map_err(|error| StunDecodeError(StunErrorLevel::Message(StunMessageError(error))))?;
222 let msg_type = MessageType::from(raw_msg.header.msg_type);
223 let mut builder = StunMessageBuilder::new(msg_type.method(), msg_type.class())
224 .with_transaction_id(TransactionId::from(raw_msg.header.transaction_id));
225
226 let attributes = RawAttributes::from(raw_msg.attributes);
228 let mut iter = attributes.into_fallible_iter();
229 let mut index = MESSAGE_HEADER_SIZE;
230 let mut position = 0;
231
232 let mut filter = AttributeFilter::default();
233 let ignore = match self.ctx.as_ref() {
234 Some(ctx) => !ctx.not_ignore,
235 None => true,
236 };
237
238 while let Some(raw_attr) = iter.next().map_err(|error| {
239 StunDecodeError(StunErrorLevel::Attribute(StunAttributeError {
240 attr_type: None,
241 position,
242 error,
243 }))
244 })? {
245 let ctx =
246 AttributeDecoderContext::new(self.ctx.clone(), &buffer[0..index], raw_attr.value);
247 let attr_type: AttributeType = raw_attr.attr_type.into();
248 let (attr, _) = match get_handler(attr_type) {
249 Some(handler) => handler(ctx).map_err(|error| {
250 StunDecodeError(StunErrorLevel::Attribute(StunAttributeError {
251 attr_type: Some(attr_type),
252 position,
253 error,
254 }))
255 })?,
256 None => (
257 Unknown::new(
258 attr_type,
259 match self.ctx.as_ref() {
260 Some(ctx) => ctx.with_unknown_data().then_some(raw_attr.value),
261 None => None,
262 },
263 )
264 .into(),
265 raw_attr.value.len(),
266 ),
267 };
268
269 if !ignore_attribute(&mut filter, attr_type) || !ignore {
270 validate_attribute(&attr, &self.ctx, buffer).map_err(|error| {
271 StunDecodeError(StunErrorLevel::Attribute(StunAttributeError {
272 attr_type: Some(attr_type),
273 position,
274 error,
275 }))
276 })?;
277
278 builder = builder.with_attribute(attr);
279 }
280
281 index = MESSAGE_HEADER_SIZE + iter.pos();
282 position += 1;
283 }
284
285 Ok((builder.build(), size))
286 }
287
288 pub fn get_context(&self) -> Option<&DecoderContext> {
290 self.ctx.as_ref()
291 }
292}
293
294#[cfg(feature = "experiments")]
295#[derive(Debug, PartialEq, Eq, Clone)]
298pub enum StunPadding {
299 Custom(u8),
301 Random,
303}
304
305#[derive(Debug, Default)]
307pub struct EncoderContextBuilder(EncoderContext);
308impl EncoderContextBuilder {
309 #[cfg(feature = "experiments")]
310 pub fn with_custom_padding(mut self, padding: StunPadding) -> Self {
320 self.0.padding = Some(padding);
321 self
322 }
323
324 pub fn build(self) -> EncoderContext {
326 self.0
327 }
328}
329
330#[derive(Debug, Default, PartialEq, Eq, Clone)]
333pub struct EncoderContext {
334 #[cfg(feature = "experiments")]
335 padding: Option<StunPadding>,
336}
337
338impl EncoderContext {
339 #[cfg(feature = "experiments")]
340 pub fn padding(&self) -> u8 {
342 self.padding
343 .as_ref()
344 .map_or(DEFAULT_PADDING_VALUE, |padding| match padding {
345 StunPadding::Random => {
346 use rand::Rng;
347 let mut rng = rand::rng();
348 rng.random()
349 }
350 StunPadding::Custom(v) => *v,
351 })
352 }
353
354 #[cfg(not(feature = "experiments"))]
355 pub fn padding(&self) -> u8 {
357 DEFAULT_PADDING_VALUE
358 }
359}
360
361#[derive(Debug, Default)]
363pub struct MessageEncoderBuilder(MessageEncoder);
364impl MessageEncoderBuilder {
365 pub fn with_context(mut self, ctx: EncoderContext) -> Self {
367 self.0.ctx = Some(ctx);
368 self
369 }
370
371 pub fn build(self) -> MessageEncoder {
373 self.0
374 }
375}
376
377#[derive(Debug, Default)]
378pub(crate) struct AttributeEncoderContext<'a> {
379 ctx: Option<EncoderContext>,
380 encoded_msg: &'a [u8],
381 raw_value: &'a mut [u8],
382}
383
384impl<'a> AttributeEncoderContext<'a> {
385 pub(crate) fn new(
386 ctx: Option<EncoderContext>,
387 encoded_msg: &'a [u8],
388 raw_value: &'a mut [u8],
389 ) -> Self {
390 Self {
391 ctx,
392 encoded_msg,
393 raw_value,
394 }
395 }
396 pub fn context(&self) -> Option<EncoderContext> {
397 self.ctx.clone()
398 }
399
400 pub fn encoded_message(&self) -> &'a [u8] {
401 self.encoded_msg
402 }
403
404 pub fn raw_value(&self) -> &[u8] {
405 self.raw_value
406 }
407
408 pub fn raw_value_mut(&mut self) -> &mut [u8] {
409 self.raw_value
410 }
411}
412
413#[derive(Debug, Default, Clone)]
415pub struct MessageEncoder {
416 ctx: Option<EncoderContext>,
417}
418
419impl MessageEncoder {
420 pub fn encode(&self, buffer: &mut [u8], msg: &StunMessage) -> Result<usize, StunEncodeError> {
428 check_buffer_boundaries(buffer, MESSAGE_HEADER_SIZE)
429 .map_err(|error| StunEncodeError(StunErrorLevel::Message(StunMessageError(error))))?;
430
431 MessageType::new(msg.method(), msg.class())
432 .encode(buffer)
433 .map_err(|error| StunEncodeError(StunErrorLevel::Message(StunMessageError(error))))?;
434
435 let mut length = 0;
436 BigEndian::write_u16(&mut buffer[2..4], length);
437 BigEndian::write_u32(&mut buffer[4..8], MAGIC_COOKIE.as_u32());
438 buffer[8..20].copy_from_slice(msg.transaction_id().as_bytes());
439
440 for (position, attr) in msg.attributes().iter().enumerate() {
441 let coded_index = length + MESSAGE_HEADER_SIZE as u16;
442 let (raw_msg, attributes) = buffer.split_at_mut(coded_index.into());
443
444 check_buffer_boundaries(attributes, ATTRIBUTE_HEADER_SIZE).map_err(|error| {
447 StunEncodeError(StunErrorLevel::Attribute(StunAttributeError {
448 attr_type: Some(attr.attribute_type()),
449 position,
450 error,
451 }))
452 })?;
453 let attr_ctx = AttributeEncoderContext::new(
455 self.ctx.clone(),
456 raw_msg,
457 &mut attributes[ATTRIBUTE_HEADER_SIZE..],
458 );
459 let value_size = attr.encode(attr_ctx).map_err(|error| {
460 StunEncodeError(StunErrorLevel::Attribute(StunAttributeError {
461 attr_type: Some(attr.attribute_type()),
462 position,
463 error,
464 }))
465 })?;
466
467 BigEndian::write_u16(&mut attributes[..2], attr.attribute_type().into());
469 BigEndian::write_u16(
470 &mut attributes[2..4],
471 value_size.try_into().map_err(|error| {
472 StunEncodeError(StunErrorLevel::Attribute(StunAttributeError {
473 attr_type: Some(attr.attribute_type()),
474 position,
475 error: StunError::from_error(StunErrorType::InvalidParam, Box::new(error)),
476 }))
477 })?,
478 );
479
480 let attr_size = ATTRIBUTE_HEADER_SIZE + value_size;
481
482 let padding_size = padding(value_size);
484 let padding_value = match self.ctx.as_ref() {
485 Some(ctx) => ctx.padding(),
486 _ => DEFAULT_PADDING_VALUE,
487 };
488 fill_padding_value(&mut attributes[attr_size..], padding_size, padding_value).map_err(
490 |error| {
491 StunEncodeError(StunErrorLevel::Attribute(StunAttributeError {
492 attr_type: Some(attr.attribute_type()),
493 position,
494 error,
495 }))
496 },
497 )?;
498
499 length += u16::try_from(attr_size + padding_size).map_err(|error| {
501 StunEncodeError(StunErrorLevel::Attribute(StunAttributeError {
502 attr_type: Some(attr.attribute_type()),
503 position,
504 error: StunError::from_error(StunErrorType::InvalidParam, Box::new(error)),
505 }))
506 })?;
507 BigEndian::write_u16(&mut raw_msg[2..4], length);
508
509 let coded_value =
511 &mut attributes[ATTRIBUTE_HEADER_SIZE..ATTRIBUTE_HEADER_SIZE + value_size];
512 let ctx = AttributeEncoderContext::new(None, raw_msg, coded_value);
513 attr.post_encode(ctx).map_err(|error| {
514 StunEncodeError(StunErrorLevel::Attribute(StunAttributeError {
515 attr_type: Some(attr.attribute_type()),
516 position,
517 error,
518 }))
519 })?;
520 }
521
522 Ok((length + MESSAGE_HEADER_SIZE as u16).into())
523 }
524}
525
526#[cfg(test)]
527mod tests {
528 use super::*;
529 use crate::attributes::stun::{Software, UserName, XorMappedAddress};
530 use crate::methods::BINDING;
531 use crate::MessageClass;
532 use std::net::{IpAddr, Ipv4Addr};
533
534 #[test]
535 fn test_ignore_attribute() {
536 let mut filter = AttributeFilter::default();
537 assert!(!ignore_attribute(&mut filter, XorMappedAddress::get_type()));
538 assert!(!ignore_attribute(&mut filter, MessageIntegrity::get_type()));
539 assert!(ignore_attribute(&mut filter, UserName::get_type()));
540 assert!(!ignore_attribute(
541 &mut filter,
542 MessageIntegritySha256::get_type()
543 ));
544 assert!(ignore_attribute(&mut filter, Software::get_type()));
545 assert!(!ignore_attribute(&mut filter, Fingerprint::get_type()));
546 assert!(ignore_attribute(&mut filter, Software::get_type()));
547
548 let mut filter = AttributeFilter::default();
549 assert!(!ignore_attribute(&mut filter, Software::get_type()));
550 assert!(!ignore_attribute(
551 &mut filter,
552 MessageIntegritySha256::get_type()
553 ));
554 assert!(ignore_attribute(&mut filter, UserName::get_type()));
555 assert!(ignore_attribute(&mut filter, MessageIntegrity::get_type()));
556 assert!(!ignore_attribute(&mut filter, Fingerprint::get_type()));
557 assert!(ignore_attribute(&mut filter, UserName::get_type()));
558
559 let mut filter = AttributeFilter::default();
560 assert!(!ignore_attribute(&mut filter, XorMappedAddress::get_type()));
561 assert!(!ignore_attribute(&mut filter, Fingerprint::get_type()));
562 assert!(ignore_attribute(&mut filter, UserName::get_type()));
563 assert!(ignore_attribute(
564 &mut filter,
565 MessageIntegritySha256::get_type()
566 ));
567 assert!(ignore_attribute(&mut filter, MessageIntegrity::get_type()));
568 }
569
570 #[test]
571 fn message_decoder() {
572 let sample_ipv4_response = [
577 0x01, 0x01, 0x00, 0x3c, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x00, 0x20, 0x00, 0x08, 0x00, 0x01, 0xa1, 0x47, 0xe1, 0x12, 0xa6, 0x43, 0x00, 0x08, 0x00, 0x14, 0x2b, 0x91, 0xf5, 0x99, 0xfd, 0x9e, 0x90, 0xc3, 0x8c, 0x74, 0x89, 0xf9, 0x2a, 0xf9, 0xba, 0x53, 0xf0, 0x6b, 0xe7, 0xd7, 0x80, 0x28, 0x00, 0x04, 0xc0, 0x7d, 0x4c, 0x96, ];
598
599 let ctx = DecoderContextBuilder::default()
601 .with_key(
602 HMACKey::new_short_term("VOkJxbRl1RmTxUk/WvJxBt")
603 .expect("Can not create new_short_term credential"),
604 )
605 .with_validation()
606 .build();
607
608 let decoder = MessageDecoderBuilder::default().with_context(ctx).build();
610 assert!(decoder.get_context().is_some());
611
612 let (msg, size) = decoder
613 .decode(&sample_ipv4_response)
614 .expect("Unable to decode buffer");
615 assert_eq!(size, sample_ipv4_response.len());
616
617 assert_eq!(msg.method(), BINDING);
619 assert_eq!(msg.class(), MessageClass::SuccessResponse);
620
621 let software = msg.get::<Software>().unwrap().expect_software();
622 assert_eq!(software.as_str(), "test vector");
623
624 let xor_addr = msg
625 .get::<XorMappedAddress>()
626 .unwrap()
627 .expect_xor_mapped_address();
628 let socket = xor_addr.socket_address();
629 assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(192, 0, 2, 1)));
630 assert_eq!(socket.port(), 32853);
631 assert!(socket.is_ipv4());
632 }
633
634 #[cfg(feature = "experiments")]
635 #[test]
636 fn message_encoder_custom_padding() {
637 let padding_value = 0x02;
638 let mut buffer: [u8; 30] = [0x0; 30];
639
640 let msg = StunMessageBuilder::new(BINDING, MessageClass::Request)
642 .with_attribute(UserName::try_from("TT").unwrap())
643 .build();
644
645 let ctx = EncoderContextBuilder::default()
647 .with_custom_padding(StunPadding::Custom(padding_value))
648 .build();
649
650 let encoder = MessageEncoderBuilder::default().with_context(ctx).build();
652 let size = encoder
653 .encode(&mut buffer, &msg)
654 .expect("Could not encode value");
655 assert_eq!(size, 28);
656
657 assert_eq!(buffer[24], 0x54); assert_eq!(buffer[25], 0x54); assert_eq!(buffer[26], padding_value); assert_eq!(buffer[27], padding_value); assert_eq!(buffer[28], 0x00);
665 assert_eq!(buffer[29], 0x00);
666 }
667
668 #[test]
669 fn message_encoder_default_padding() {
670 let padding_value = 0x00;
671 let mut buffer: [u8; 30] = [0x0; 30];
672
673 let msg = StunMessageBuilder::new(BINDING, MessageClass::Request)
675 .with_attribute(UserName::try_from("TT").unwrap())
676 .build();
677
678 let ctx = EncoderContextBuilder::default().build();
680
681 let encoder = MessageEncoderBuilder::default().with_context(ctx).build();
683 let size = encoder
684 .encode(&mut buffer, &msg)
685 .expect("Could not encode value");
686 assert_eq!(size, 28);
687
688 assert_eq!(buffer[24], 0x54); assert_eq!(buffer[25], 0x54); assert_eq!(buffer[26], padding_value); assert_eq!(buffer[27], padding_value); assert_eq!(buffer[28], 0x00);
696 assert_eq!(buffer[29], 0x00);
697 }
698}