1macro_rules! bytewise_xor {
103 ($size:literal, $a:expr, $b:expr, $default:literal) => {{
104 let mut arr = [$default; $size];
105 for (i, item) in arr.iter_mut().enumerate() {
106 *item = $a[i] ^ $b[i];
107 }
108 arr
109 }};
110}
111
112mod address;
113pub use address::{MappedSocketAddr, XorSocketAddr};
114mod alternate;
115pub use alternate::{AlternateDomain, AlternateServer};
116mod error;
117pub use error::{ErrorCode, UnknownAttributes};
118mod ice;
119pub use ice::{IceControlled, IceControlling, Priority, UseCandidate};
120mod integrity;
121pub use integrity::{MessageIntegrity, MessageIntegritySha256};
122mod fingerprint;
123pub use fingerprint::Fingerprint;
124mod nonce;
125pub use nonce::Nonce;
126mod password_algorithm;
127pub use password_algorithm::{PasswordAlgorithm, PasswordAlgorithmValue, PasswordAlgorithms};
128mod realm;
129pub use realm::Realm;
130mod user;
131pub use user::{Userhash, Username};
132mod software;
133pub use software::Software;
134mod xor_addr;
135pub use xor_addr::XorMappedAddress;
136
137use crate::data::Data;
138use crate::message::{StunParseError, StunWriteError};
139
140use byteorder::{BigEndian, ByteOrder};
141
142#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
144pub struct AttributeType(u16);
145
146impl std::fmt::Display for AttributeType {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
149 }
150}
151
152impl AttributeType {
153 pub const fn new(val: u16) -> Self {
163 Self(val)
164 }
165
166 pub fn value(&self) -> u16 {
176 self.0
177 }
178
179 pub fn name(self) -> &'static str {
187 match self {
188 AttributeType(0x0001) => "MAPPED-ADDRESS",
189 Username::TYPE => "USERNAME",
190 MessageIntegrity::TYPE => "MESSAGE-INTEGRITY",
191 ErrorCode::TYPE => "ERROR-CODE",
192 UnknownAttributes::TYPE => "UNKNOWN-ATTRIBUTES",
193 Realm::TYPE => "REALM",
194 Nonce::TYPE => "NONCE",
195 MessageIntegritySha256::TYPE => "MESSAGE-INTEGRITY-SHA256",
196 PasswordAlgorithm::TYPE => "PASSWORD-ALGORITHM",
197 Userhash::TYPE => "USERHASH",
198 XorMappedAddress::TYPE => "XOR-MAPPED-ADDRESS",
199 PasswordAlgorithms::TYPE => "PASSWORD_ALGORITHMS",
200 AlternateDomain::TYPE => "ALTERNATE-DOMAIN",
201 Software::TYPE => "SOFTWARE",
202 AlternateServer::TYPE => "ALTERNATE-SERVER",
203 Fingerprint::TYPE => "FINGERPRINT",
204 Priority::TYPE => "PRIORITY",
205 UseCandidate::TYPE => "USE-CANDIDATE",
206 IceControlled::TYPE => "ICE-CONTROLLED",
207 IceControlling::TYPE => "ICE-CONTROLLING",
208 _ => "unknown",
209 }
210 }
211
212 pub fn comprehension_required(self) -> bool {
223 self.0 < 0x8000
224 }
225}
226impl From<u16> for AttributeType {
227 fn from(f: u16) -> Self {
228 Self::new(f)
229 }
230}
231impl From<AttributeType> for u16 {
232 fn from(f: AttributeType) -> Self {
233 f.0
234 }
235}
236
237#[derive(Debug, Copy, Clone, PartialEq, Eq)]
239pub struct AttributeHeader {
240 atype: AttributeType,
241 length: u16,
242}
243
244impl AttributeHeader {
245 fn parse(data: &[u8]) -> Result<Self, StunParseError> {
246 if data.len() < 4 {
247 return Err(StunParseError::Truncated {
248 expected: 4,
249 actual: data.len(),
250 });
251 }
252 let ret = Self {
253 atype: BigEndian::read_u16(&data[0..2]).into(),
254 length: BigEndian::read_u16(&data[2..4]),
255 };
256 Ok(ret)
257 }
258
259 fn to_bytes(self) -> Vec<u8> {
260 let mut ret = vec![0; 4];
261 self.write_into(&mut ret);
262 ret
263 }
264
265 fn write_into(&self, ret: &mut [u8]) {
266 BigEndian::write_u16(&mut ret[0..2], self.atype.into());
267 BigEndian::write_u16(&mut ret[2..4], self.length);
268 }
269
270 pub fn get_type(&self) -> AttributeType {
272 self.atype
273 }
274
275 pub fn length(&self) -> u16 {
277 self.length
278 }
279}
280impl From<AttributeHeader> for Vec<u8> {
281 fn from(f: AttributeHeader) -> Self {
282 f.to_bytes()
283 }
284}
285impl TryFrom<&[u8]> for AttributeHeader {
286 type Error = StunParseError;
287
288 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
289 AttributeHeader::parse(value)
290 }
291}
292
293pub trait AttributeStaticType {
295 const TYPE: AttributeType;
297}
298
299pub trait Attribute: std::fmt::Debug + std::marker::Sync {
301 fn get_type(&self) -> AttributeType;
303
304 fn length(&self) -> u16;
307}
308pub trait AttributeFromRaw<E>:
333 Attribute + for<'a> TryFrom<&'a RawAttribute<'a>, Error = E>
334{
335 fn from_raw(raw: &RawAttribute) -> Result<Self, E>
337 where
338 Self: Sized;
339}
340
341impl<E, T: Attribute + for<'a> TryFrom<&'a RawAttribute<'a>, Error = E>> AttributeFromRaw<E> for T {
342 fn from_raw(raw: &RawAttribute) -> Result<T, E> {
343 Self::try_from(raw)
344 }
345}
346
347fn padded_attr_len(len: usize) -> usize {
348 if len % 4 == 0 {
349 len
350 } else {
351 len + 4 - len % 4
352 }
353}
354
355pub trait AttributeExt {
357 fn padded_len(&self) -> usize;
360}
361
362impl<A: Attribute + ?Sized> AttributeExt for A {
363 fn padded_len(&self) -> usize {
364 4 + padded_attr_len(self.length() as usize)
365 }
366}
367
368pub trait AttributeWrite: Attribute {
370 fn write_into_unchecked(&self, dest: &mut [u8]);
375 fn to_raw(&self) -> RawAttribute;
377}
378
379pub trait AttributeWriteExt: AttributeWrite {
382 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize;
387 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
390 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
393}
394
395impl<A: AttributeWrite + ?Sized> AttributeWriteExt for A {
396 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
397 if dest.len() < 4 {
398 return Err(StunWriteError::TooSmall {
399 expected: 4,
400 actual: dest.len(),
401 });
402 }
403 self.write_header_unchecked(dest);
404 Ok(4)
405 }
406 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize {
407 AttributeHeader {
408 atype: self.get_type(),
409 length: self.length(),
410 }
411 .write_into(dest);
412 4
413 }
414
415 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
416 let len = self.padded_len();
417 if len > dest.len() {
418 return Err(StunWriteError::TooSmall {
419 expected: len,
420 actual: dest.len(),
421 });
422 }
423 self.write_into_unchecked(dest);
424 Ok(len)
425 }
426}
427
428#[derive(Debug, Clone, PartialEq, Eq)]
430pub struct RawAttribute<'a> {
431 pub header: AttributeHeader,
433 pub value: Data<'a>,
435}
436
437macro_rules! display_attr {
438 ($this:ident, $CamelType:ty, $default:ident) => {{
439 if let Ok(attr) = <$CamelType>::from_raw($this) {
440 format!("{}", attr)
441 } else {
442 $default
443 }
444 }};
445}
446
447impl<'a> std::fmt::Display for RawAttribute<'a> {
448 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
449 let malformed_str = format!(
451 "{}(Malformed): len: {}, data: {:?})",
452 self.get_type(),
453 self.header.length(),
454 self.value
455 );
456 let display_str = match self.get_type() {
457 Username::TYPE => display_attr!(self, Username, malformed_str),
458 MessageIntegrity::TYPE => display_attr!(self, MessageIntegrity, malformed_str),
459 ErrorCode::TYPE => display_attr!(self, ErrorCode, malformed_str),
460 UnknownAttributes::TYPE => display_attr!(self, UnknownAttributes, malformed_str),
461 Realm::TYPE => display_attr!(self, Realm, malformed_str),
462 Nonce::TYPE => display_attr!(self, Nonce, malformed_str),
463 MessageIntegritySha256::TYPE => {
464 display_attr!(self, MessageIntegritySha256, malformed_str)
465 }
466 PasswordAlgorithm::TYPE => display_attr!(self, PasswordAlgorithm, malformed_str),
467 XorMappedAddress::TYPE => display_attr!(self, XorMappedAddress, malformed_str),
469 PasswordAlgorithms::TYPE => display_attr!(self, PasswordAlgorithms, malformed_str),
470 AlternateDomain::TYPE => display_attr!(self, AlternateDomain, malformed_str),
471 Software::TYPE => display_attr!(self, Software, malformed_str),
472 AlternateServer::TYPE => display_attr!(self, AlternateServer, malformed_str),
473 Fingerprint::TYPE => display_attr!(self, Fingerprint, malformed_str),
474 Priority::TYPE => display_attr!(self, Priority, malformed_str),
475 UseCandidate::TYPE => display_attr!(self, UseCandidate, malformed_str),
476 IceControlled::TYPE => display_attr!(self, IceControlled, malformed_str),
477 IceControlling::TYPE => display_attr!(self, IceControlling, malformed_str),
478 _ => format!(
479 "RawAttribute (type: {:?}, len: {}, data: {:?})",
480 self.header.get_type(),
481 self.header.length(),
482 &self.value
483 ),
484 };
485 write!(f, "{}", display_str)
486 }
487}
488
489impl<'a> RawAttribute<'a> {
490 pub fn new(atype: AttributeType, data: &'a [u8]) -> Self {
492 Self {
493 header: AttributeHeader {
494 atype,
495 length: data.len() as u16,
496 },
497 value: data.into(),
498 }
499 }
500
501 pub fn new_owned(atype: AttributeType, data: Box<[u8]>) -> Self {
503 Self {
504 header: AttributeHeader {
505 atype,
506 length: data.len() as u16,
507 },
508 value: data.into(),
509 }
510 }
511
512 pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
524 let header = AttributeHeader::parse(data)?;
525 if header.length() > (data.len() - 4) as u16 {
527 return Err(StunParseError::Truncated {
528 expected: header.length() as usize,
529 actual: data.len() - 4,
530 });
531 }
532 Ok(Self {
533 header,
534 value: Data::Borrowed(data[4..header.length() as usize + 4].into()),
535 })
536 }
537
538 pub fn to_bytes(&self) -> Vec<u8> {
548 let mut vec = Vec::with_capacity(self.padded_len());
549 let mut header_bytes = [0; 4];
550 self.header.write_into(&mut header_bytes);
551 vec.extend(&header_bytes);
552 vec.extend(&*self.value);
553 let len = vec.len();
554 if len % 4 != 0 {
555 vec.resize(len + 4 - (len % 4), 0);
557 }
558 vec
559 }
560
561 pub fn check_type_and_len(
563 &self,
564 atype: AttributeType,
565 allowed_range: impl std::ops::RangeBounds<usize>,
566 ) -> Result<(), StunParseError> {
567 if self.header.get_type() != atype {
568 return Err(StunParseError::WrongAttributeImplementation);
569 }
570 check_len(self.value.len(), allowed_range)
571 }
572
573 pub fn into_owned<'b>(self) -> RawAttribute<'b> {
575 RawAttribute {
576 header: self.header,
577 value: self.value.into_owned(),
578 }
579 }
580}
581
582impl<'a> Attribute for RawAttribute<'a> {
583 fn get_type(&self) -> AttributeType {
585 self.header.get_type()
586 }
587
588 fn length(&self) -> u16 {
590 self.value.len() as u16
591 }
592}
593
594impl<'a> AttributeWrite for RawAttribute<'a> {
595 fn write_into_unchecked(&self, dest: &mut [u8]) {
597 let len = self.padded_len();
598 self.header.write_into(dest);
599 let mut offset = 4;
600 dest[offset..offset + self.value.len()].copy_from_slice(&self.value);
601 offset += self.value.len();
602 if len - offset > 0 {
603 dest[offset..len].fill(0);
604 }
605 }
606
607 fn to_raw(&self) -> RawAttribute<'a> {
608 self.clone()
609 }
610}
611
612impl<'a, A: AttributeWrite> From<&'a A> for RawAttribute<'a> {
613 fn from(value: &'a A) -> Self {
614 value.to_raw()
615 }
616}
617
618fn check_len(
619 len: usize,
620 allowed_range: impl std::ops::RangeBounds<usize>,
621) -> Result<(), StunParseError> {
622 match allowed_range.start_bound() {
623 std::ops::Bound::Unbounded => (),
624 std::ops::Bound::Included(start) => {
625 if len < *start {
626 return Err(StunParseError::Truncated {
627 expected: *start,
628 actual: len,
629 });
630 }
631 }
632 std::ops::Bound::Excluded(start) => {
633 if len <= *start {
634 return Err(StunParseError::Truncated {
635 expected: start + 1,
636 actual: len,
637 });
638 }
639 }
640 }
641 match allowed_range.end_bound() {
642 std::ops::Bound::Unbounded => (),
643 std::ops::Bound::Included(end) => {
644 if len > *end {
645 return Err(StunParseError::TooLarge {
646 expected: *end,
647 actual: len,
648 });
649 }
650 }
651 std::ops::Bound::Excluded(end) => {
652 if len >= *end {
653 return Err(StunParseError::TooLarge {
654 expected: *end - 1,
655 actual: len,
656 });
657 }
658 }
659 }
660 Ok(())
661}
662
663impl<'a> From<RawAttribute<'a>> for Vec<u8> {
664 fn from(f: RawAttribute) -> Self {
665 f.to_bytes()
666 }
667}
668
669#[cfg(test)]
670mod tests {
671 use super::*;
672
673 #[test]
674 fn attribute_type() {
675 let _log = crate::tests::test_init_log();
676 let atype = ErrorCode::TYPE;
677 let anum: u16 = atype.into();
678 assert_eq!(atype, anum.into());
679 }
680
681 #[test]
682 fn short_attribute_header() {
683 let _log = crate::tests::test_init_log();
684 let data = [0; 1];
685 let res: Result<AttributeHeader, _> = data.as_ref().try_into();
687 assert!(res.is_err());
688 }
689
690 #[test]
691 fn raw_attribute_construct() {
692 let _log = crate::tests::test_init_log();
693 let a = RawAttribute::new(1.into(), &[80, 160]);
694 assert_eq!(a.get_type(), 1.into());
695 let bytes: Vec<_> = a.into();
696 assert_eq!(bytes, &[0, 1, 0, 2, 80, 160, 0, 0]);
697 let b = RawAttribute::from_bytes(bytes.as_ref()).unwrap();
698 assert_eq!(b.get_type(), 1.into());
699 }
700
701 #[test]
702 fn raw_attribute_encoding() {
703 let _log = crate::tests::test_init_log();
704 let orig = RawAttribute::new(1.into(), &[80, 160]);
705 assert_eq!(orig.get_type(), 1.into());
706 let mut data: Vec<_> = orig.into();
707 let len = data.len();
708 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 + 1);
710 assert!(matches!(
711 RawAttribute::from_bytes(data.as_ref()),
712 Err(StunParseError::Truncated {
713 expected: 5,
714 actual: 4
715 })
716 ));
717 }
718
719 #[test]
720 fn test_check_len() {
721 let _log = crate::tests::test_init_log();
722 assert!(check_len(4, ..).is_ok());
723 assert!(check_len(4, 0..).is_ok());
724 assert!(check_len(4, 0..8).is_ok());
725 assert!(check_len(4, 0..=8).is_ok());
726 assert!(check_len(4, ..=8).is_ok());
727 assert!(matches!(
728 check_len(4, ..4),
729 Err(StunParseError::TooLarge {
730 expected: 3,
731 actual: 4
732 })
733 ));
734 assert!(matches!(
735 check_len(4, 5..),
736 Err(StunParseError::Truncated {
737 expected: 5,
738 actual: 4
739 })
740 ));
741 assert!(matches!(
742 check_len(4, ..=3),
743 Err(StunParseError::TooLarge {
744 expected: 3,
745 actual: 4
746 })
747 ));
748 assert!(matches!(
749 check_len(
750 4,
751 (std::ops::Bound::Excluded(4), std::ops::Bound::Unbounded)
752 ),
753 Err(StunParseError::Truncated {
754 expected: 5,
755 actual: 4
756 })
757 ));
758 }
759}