1#[cfg(feature = "std")]
88use alloc::collections::BTreeMap;
89use alloc::string::String;
90use alloc::vec;
91use alloc::vec::Vec;
92use core::convert::TryFrom;
93#[cfg(feature = "std")]
94use std::sync::{Mutex, OnceLock};
95
96use byteorder::{BigEndian, ByteOrder};
97
98use crate::attribute::*;
99
100use tracing::{trace, warn};
101
102pub const MAGIC_COOKIE: u32 = 0x2112A442;
104
105#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
107pub struct Method(u16);
108
109impl core::fmt::Display for Method {
110 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111 write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
112 }
113}
114
115#[cfg(feature = "std")]
116static METHOD_NAME_MAP: OnceLock<Mutex<BTreeMap<Method, &'static str>>> = OnceLock::new();
117
118impl Method {
119 #[cfg(feature = "std")]
121 pub fn add_name(self, name: &'static str) {
122 let mut mnames = METHOD_NAME_MAP
123 .get_or_init(Default::default)
124 .lock()
125 .unwrap();
126 mnames.insert(self, name);
127 }
128
129 pub const fn new(val: u16) -> Self {
141 if val >= 0xf000 {
142 panic!("Method value is out of range!");
143 }
144 Self(val)
145 }
146
147 pub fn value(&self) -> u16 {
157 self.0
158 }
159
160 pub fn name(self) -> &'static str {
168 match self {
169 BINDING => "BINDING",
170 _ => {
171 #[cfg(feature = "std")]
172 {
173 let mnames = METHOD_NAME_MAP
174 .get_or_init(Default::default)
175 .lock()
176 .unwrap();
177 if let Some(name) = mnames.get(&self) {
178 return name;
179 }
180 }
181 "unknown"
182 }
183 }
184 }
185}
186
187pub const BINDING: Method = Method::new(0x0001);
190
191#[derive(Debug, thiserror::Error)]
193#[non_exhaustive]
194pub enum StunParseError {
195 #[error("The provided data is not a STUN message")]
197 NotStun,
198 #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
200 Truncated {
201 expected: usize,
203 actual: usize,
205 },
206 #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
208 TooLarge {
209 expected: usize,
211 actual: usize,
213 },
214 #[error("Integrity value does not match")]
216 IntegrityCheckFailed,
217 #[error("Missing attribute {}", .0)]
219 MissingAttribute(AttributeType),
220 #[error("An attribute {} was encountered after a message integrity attribute", .0)]
222 AttributeAfterIntegrity(AttributeType),
223 #[error("An attribute {} was encountered after a fingerprint attribute", .0)]
225 AttributeAfterFingerprint(AttributeType),
226 #[error("Fingerprint does not match")]
228 FingerprintMismatch,
229 #[error("The provided data does not match the message")]
231 DataMismatch,
232 #[error("The attribute contains invalid data")]
234 InvalidAttributeData,
235 #[error("Cannot parse with this attribute")]
237 WrongAttributeImplementation,
238}
239
240#[derive(Debug, thiserror::Error)]
242#[non_exhaustive]
243pub enum StunWriteError {
244 #[error("The attribute already exists in the message")]
246 AttributeExists(AttributeType),
247 #[error("The message already contains a fingerprint attribute")]
249 FingerprintExists,
250 #[error("The message already contains a message intregrity attribute")]
252 MessageIntegrityExists,
253 #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
255 TooLarge {
256 expected: usize,
258 actual: usize,
260 },
261 #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
263 TooSmall {
264 expected: usize,
266 actual: usize,
268 },
269 #[error("Failed to compute integrity")]
271 IntegrityFailed,
272 #[error("Out of range input provided")]
274 OutOfRange {
275 value: usize,
277 min: usize,
279 max: usize,
281 },
282}
283
284#[derive(Debug, Clone, PartialEq, Eq)]
286#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
287pub struct LongTermCredentials {
288 username: String,
289 password: String,
290 realm: String,
291}
292
293impl LongTermCredentials {
294 pub fn new(username: String, password: String, realm: String) -> Self {
310 Self {
311 username,
312 password,
313 realm,
314 }
315 }
316
317 pub fn username(&self) -> &str {
319 &self.username
320 }
321
322 pub fn password(&self) -> &str {
324 &self.password
325 }
326
327 pub fn realm(&self) -> &str {
329 &self.realm
330 }
331}
332
333#[derive(Debug, Clone, PartialEq, Eq)]
335#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
336pub struct ShortTermCredentials {
337 password: String,
338}
339
340impl ShortTermCredentials {
341 pub fn new(password: String) -> Self {
351 Self { password }
352 }
353
354 pub fn password(&self) -> &str {
356 &self.password
357 }
358}
359
360#[derive(Debug, Clone, PartialEq, Eq)]
364#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
365pub enum MessageIntegrityCredentials {
366 ShortTerm(ShortTermCredentials),
368 LongTerm(LongTermCredentials),
370}
371
372impl From<LongTermCredentials> for MessageIntegrityCredentials {
373 fn from(value: LongTermCredentials) -> Self {
374 MessageIntegrityCredentials::LongTerm(value)
375 }
376}
377
378impl From<ShortTermCredentials> for MessageIntegrityCredentials {
379 fn from(value: ShortTermCredentials) -> Self {
380 MessageIntegrityCredentials::ShortTerm(value)
381 }
382}
383
384impl MessageIntegrityCredentials {
385 fn make_hmac_key(&self) -> Vec<u8> {
386 match self {
387 MessageIntegrityCredentials::ShortTerm(short) => short.password.clone().into(),
388 MessageIntegrityCredentials::LongTerm(long) => {
389 use md5::{Digest, Md5};
390 let data = long.username.clone()
391 + ":"
392 + &long.realm.clone()
393 + ":"
394 + &long.password.clone();
395 let mut digest = Md5::new();
396 digest.update(&data);
397 digest.finalize().to_vec()
398 }
399 }
400 }
401}
402
403#[derive(Copy, Clone, Debug, PartialEq, Eq)]
415pub enum MessageClass {
416 Request,
418 Indication,
420 Success,
422 Error,
424}
425
426impl MessageClass {
427 pub fn is_response(self) -> bool {
430 matches!(self, MessageClass::Success | MessageClass::Error)
431 }
432
433 fn to_bits(self) -> u16 {
434 match self {
435 MessageClass::Request => 0x000,
436 MessageClass::Indication => 0x010,
437 MessageClass::Success => 0x100,
438 MessageClass::Error => 0x110,
439 }
440 }
441}
442
443#[derive(Copy, Clone, Debug, PartialEq, Eq)]
445pub struct MessageType(u16);
446
447impl core::fmt::Display for MessageType {
448 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
449 write!(
450 f,
451 "MessageType(class: {:?}, method: {}",
452 self.class(),
453 self.method(),
454 )
455 }
456}
457
458impl MessageType {
459 pub fn from_class_method(class: MessageClass, method: Method) -> Self {
470 let class_bits = MessageClass::to_bits(class);
471 let method = method.value();
472 let method_bits = method & 0xf | (method & 0x70) << 1 | (method & 0xf80) << 2;
473 Self(class_bits | method_bits)
476 }
477
478 pub fn class(self) -> MessageClass {
488 let class = (self.0 & 0x10) >> 4 | (self.0 & 0x100) >> 7;
489 match class {
490 0x0 => MessageClass::Request,
491 0x1 => MessageClass::Indication,
492 0x2 => MessageClass::Success,
493 0x3 => MessageClass::Error,
494 _ => unreachable!(),
495 }
496 }
497
498 pub fn has_class(self, cls: MessageClass) -> bool {
508 self.class() == cls
509 }
510
511 pub fn is_response(self) -> bool {
527 self.class().is_response()
528 }
529
530 pub fn method(self) -> Method {
540 Method::new(self.0 & 0xf | (self.0 & 0xe0) >> 1 | (self.0 & 0x3e00) >> 2)
541 }
542
543 pub fn has_method(self, method: Method) -> bool {
553 self.method() == method
554 }
555
556 pub fn write_into(&self, dest: &mut [u8]) {
558 BigEndian::write_u16(dest, self.0);
559 }
560
561 pub fn to_bytes(self) -> Vec<u8> {
563 let mut ret = vec![0; 2];
564 BigEndian::write_u16(&mut ret[0..2], self.0);
565 ret
566 }
567
568 pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
570 let data = BigEndian::read_u16(data);
571 if data & 0xc000 != 0x0 {
572 return Err(StunParseError::NotStun);
574 }
575 Ok(Self(data))
576 }
577}
578impl TryFrom<&[u8]> for MessageType {
579 type Error = StunParseError;
580
581 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
582 MessageType::from_bytes(value)
583 }
584}
585
586#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
588pub struct TransactionId {
589 id: u128,
590}
591
592impl TransactionId {
593 pub fn generate() -> TransactionId {
595 #[cfg(not(feature = "std"))]
596 {
597 use rand_core::TryRngCore;
598 let mut dest = [0; 16];
599 rand_core::OsRng
600 .try_fill_bytes(&mut dest)
601 .expect("Cannot generate random data");
602 u128::from_be_bytes(dest).into()
603 }
604 #[cfg(feature = "std")]
605 {
606 use rand::Rng;
607 let mut rng = rand::rng();
608 rng.random::<u128>().into()
609 }
610 }
611}
612
613impl From<u128> for TransactionId {
614 fn from(id: u128) -> Self {
615 Self {
616 id: id & 0xffff_ffff_ffff_ffff_ffff_ffff,
617 }
618 }
619}
620impl From<TransactionId> for u128 {
621 fn from(id: TransactionId) -> Self {
622 id.id
623 }
624}
625impl core::fmt::Display for TransactionId {
626 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
627 write!(f, "{:#x}", self.id)
628 }
629}
630
631#[derive(Debug)]
635pub struct MessageHeader {
636 mtype: MessageType,
637 transaction_id: TransactionId,
638 length: u16,
639}
640
641impl MessageHeader {
642 pub const LENGTH: usize = 20;
644
645 pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
658 if data.len() < 20 {
659 return Err(StunParseError::Truncated {
660 expected: 20,
661 actual: data.len(),
662 });
663 }
664 let mtype = MessageType::from_bytes(data)?;
665 let mlength = BigEndian::read_u16(&data[2..]);
666 let tid = BigEndian::read_u128(&data[4..]);
667 let cookie = (tid >> 96) as u32;
668 if cookie != MAGIC_COOKIE {
669 warn!(
670 "malformed cookie constant {:?} != stored data {:?}",
671 MAGIC_COOKIE, cookie
672 );
673 return Err(StunParseError::NotStun);
674 }
675
676 Ok(Self {
677 mtype,
678 transaction_id: tid.into(),
679 length: mlength,
680 })
681 }
682
683 pub fn data_length(&self) -> u16 {
686 self.length
687 }
688
689 pub fn transaction_id(&self) -> TransactionId {
691 self.transaction_id
692 }
693
694 pub fn get_type(&self) -> MessageType {
696 self.mtype
697 }
698
699 fn new(mtype: MessageType, transaction_id: TransactionId, length: u16) -> Self {
700 Self {
701 mtype,
702 transaction_id,
703 length,
704 }
705 }
706
707 fn write_into(&self, dest: &mut [u8]) {
708 self.mtype.write_into(&mut dest[..2]);
709 let transaction: u128 = self.transaction_id.into();
710 let tid = (MAGIC_COOKIE as u128) << 96 | transaction & 0xffff_ffff_ffff_ffff_ffff_ffff;
711 BigEndian::write_u128(&mut dest[4..20], tid);
712 BigEndian::write_u16(&mut dest[2..4], self.length);
713 }
714}
715
716#[derive(Debug, Clone)]
721pub struct Message<'a> {
722 data: &'a [u8],
723}
724
725impl core::fmt::Display for Message<'_> {
726 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
727 write!(
728 f,
729 "Message(class: {:?}, method: {}, transaction: {}, attributes: ",
730 self.get_type().class(),
731 self.get_type().method(),
732 self.transaction_id()
733 )?;
734 let iter = self.iter_attributes();
735 write!(f, "[")?;
736 for (i, (_offset, a)) in iter.enumerate() {
737 if i > 0 {
738 write!(f, ", ")?;
739 }
740 write!(f, "{a}")?;
741 }
742 write!(f, "]")?;
743 write!(f, ")")
744 }
745}
746
747#[derive(Clone, Copy, Debug, PartialEq, Eq)]
749pub enum IntegrityAlgorithm {
750 Sha1,
752 Sha256,
754}
755
756impl<'a> Message<'a> {
757 pub fn builder<B: MessageWrite>(
773 mtype: MessageType,
774 transaction_id: TransactionId,
775 mut write: B,
776 ) -> B {
777 let mut data = [0; 20];
778 MessageHeader::new(mtype, transaction_id, 0).write_into(&mut data);
779 write.push_data(&data);
780 write
781 }
782
783 pub fn builder_request<B: MessageWrite>(method: Method, write: B) -> B {
797 Message::builder(
798 MessageType::from_class_method(MessageClass::Request, method),
799 TransactionId::generate(),
800 write,
801 )
802 }
803
804 pub fn builder_success<B: MessageWrite>(orig: &Message, write: B) -> B {
824 if !orig.has_class(MessageClass::Request) {
825 panic!(
826 "A success response message was attempted to be created from a non-request message"
827 );
828 }
829 Message::builder(
830 MessageType::from_class_method(MessageClass::Success, orig.method()),
831 orig.transaction_id(),
832 write,
833 )
834 }
835
836 pub fn builder_error<B: MessageWrite>(orig: &Message, write: B) -> B {
856 if !orig.has_class(MessageClass::Request) {
857 panic!(
858 "An error response message was attempted to be created from a non-request message"
859 );
860 }
861 Message::builder(
862 MessageType::from_class_method(MessageClass::Error, orig.method()),
863 orig.transaction_id(),
864 write,
865 )
866 }
867
868 pub fn builder_indication<B: MessageWrite>(method: Method, write: B) -> B {
882 Message::builder(
883 MessageType::from_class_method(MessageClass::Indication, method),
884 TransactionId::generate(),
885 write,
886 )
887 }
888
889 pub fn get_type(&self) -> MessageType {
903 MessageType::try_from(&self.data[..2]).unwrap()
904 }
905
906 pub fn class(&self) -> MessageClass {
918 self.get_type().class()
919 }
920
921 pub fn has_class(&self, cls: MessageClass) -> bool {
933 self.class() == cls
934 }
935
936 pub fn is_response(&self) -> bool {
958 self.class().is_response()
959 }
960
961 pub fn method(&self) -> Method {
973 self.get_type().method()
974 }
975
976 pub fn has_method(&self, method: Method) -> bool {
989 self.method() == method
990 }
991
992 pub fn transaction_id(&self) -> TransactionId {
1006 BigEndian::read_u128(&self.data[4..]).into()
1007 }
1008
1009 #[tracing::instrument(
1025 name = "message_from_bytes",
1026 level = "trace",
1027 skip(data),
1028 fields(
1029 data.len = data.len()
1030 )
1031 )]
1032 pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
1033 let orig_data = data;
1034
1035 let header = MessageHeader::from_bytes(data)?;
1036 let mlength = header.data_length() as usize;
1037 if mlength + MessageHeader::LENGTH > data.len() {
1038 warn!(
1040 "malformed advertised size {} and data size {} don't match",
1041 mlength + 20,
1042 data.len()
1043 );
1044 return Err(StunParseError::Truncated {
1045 expected: mlength + MessageHeader::LENGTH,
1046 actual: data.len(),
1047 });
1048 }
1049
1050 let ending_attributes = [
1051 MessageIntegrity::TYPE,
1052 MessageIntegritySha256::TYPE,
1053 Fingerprint::TYPE,
1054 ];
1055 let mut seen_ending_attributes = [AttributeType::new(0); 3];
1057 let mut seen_ending_len = 0;
1058 let mut data_offset = MessageHeader::LENGTH;
1059 for attr in MessageRawAttributesIter::new(data) {
1060 let (_offset, attr) = attr.map_err(|e| {
1061 warn!("failed to parse message attribute at offset {data_offset}: {e}",);
1062 e
1063 })?;
1064
1065 if seen_ending_len > 0 && !ending_attributes.contains(&attr.get_type()) {
1068 if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1069 warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1070 return Ok(Message { data: orig_data });
1071 } else {
1072 warn!(
1074 "unexpected attribute {} after MESSAGE_INTEGRITY",
1075 attr.get_type()
1076 );
1077 return Ok(Message { data: orig_data });
1078 }
1079 }
1080
1081 if ending_attributes.contains(&attr.get_type()) {
1082 if seen_ending_attributes.contains(&attr.get_type()) {
1083 if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1084 warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1085 return Ok(Message { data: orig_data });
1086 } else {
1087 warn!(
1089 "unexpected attribute {} after MESSAGE_INTEGRITY",
1090 attr.get_type()
1091 );
1092 return Ok(Message { data: orig_data });
1093 }
1094 } else {
1095 seen_ending_attributes[seen_ending_len] = attr.get_type();
1096 seen_ending_len += 1;
1097 }
1099 }
1100 let padded_len = attr.padded_len();
1101 if attr.get_type() == Fingerprint::TYPE {
1102 let f = Fingerprint::from_raw_ref(&attr)?;
1103 let msg_fingerprint = f.fingerprint();
1104 let mut fingerprint_data = orig_data[..data_offset].to_vec();
1105 BigEndian::write_u16(
1106 &mut fingerprint_data[2..4],
1107 (data_offset + padded_len - MessageHeader::LENGTH) as u16,
1108 );
1109 let calculated_fingerprint = Fingerprint::compute(&fingerprint_data);
1110 if &calculated_fingerprint != msg_fingerprint {
1111 warn!(
1112 "fingerprint mismatch {:?} != {:?}",
1113 calculated_fingerprint, msg_fingerprint
1114 );
1115 return Err(StunParseError::FingerprintMismatch);
1116 }
1117 }
1118 data_offset += padded_len;
1119 }
1120 Ok(Message { data: orig_data })
1121 }
1122
1123 #[tracing::instrument(
1146 name = "message_validate_integrity",
1147 level = "trace",
1148 skip(self, credentials),
1149 fields(
1150 msg.transaction = %self.transaction_id(),
1151 )
1152 )]
1153 pub fn validate_integrity(
1154 &self,
1155 credentials: &MessageIntegrityCredentials,
1156 ) -> Result<IntegrityAlgorithm, StunParseError> {
1157 let raw_sha1 = self.raw_attribute(MessageIntegrity::TYPE);
1158 let raw_sha256 = self.raw_attribute(MessageIntegritySha256::TYPE);
1159 let (algo, msg_hmac) = match (raw_sha1, raw_sha256) {
1160 (_, Some(sha256)) => {
1161 let integrity = MessageIntegritySha256::try_from(&sha256)?;
1162 (IntegrityAlgorithm::Sha256, integrity.hmac().to_vec())
1163 }
1164 (Some(sha1), None) => {
1165 let integrity = MessageIntegrity::try_from(&sha1)?;
1166 (IntegrityAlgorithm::Sha1, integrity.hmac().to_vec())
1167 }
1168 (None, None) => return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE)),
1169 };
1170
1171 let data = self.data;
1174 debug_assert!(data.len() >= MessageHeader::LENGTH);
1175 let mut data = &data[MessageHeader::LENGTH..];
1176 let mut data_offset = MessageHeader::LENGTH;
1177 while !data.is_empty() {
1178 let attr = RawAttribute::from_bytes(data)?;
1179 if algo == IntegrityAlgorithm::Sha1 && attr.get_type() == MessageIntegrity::TYPE {
1180 let msg = MessageIntegrity::try_from(&attr)?;
1181 debug_assert!(msg.hmac().as_slice() == msg_hmac);
1182
1183 let key = credentials.make_hmac_key();
1186 let mut hmac_data = self.data[..data_offset].to_vec();
1187 BigEndian::write_u16(
1188 &mut hmac_data[2..4],
1189 data_offset as u16 + 24 - MessageHeader::LENGTH as u16,
1190 );
1191 MessageIntegrity::verify(
1192 &hmac_data,
1193 &key,
1194 msg_hmac.as_slice().try_into().unwrap(),
1195 )?;
1196 return Ok(algo);
1197 } else if algo == IntegrityAlgorithm::Sha256
1198 && attr.get_type() == MessageIntegritySha256::TYPE
1199 {
1200 let msg = MessageIntegritySha256::try_from(&attr)?;
1201 debug_assert!(msg.hmac() == msg_hmac);
1202
1203 let key = credentials.make_hmac_key();
1206 let mut hmac_data = self.data[..data_offset].to_vec();
1207 BigEndian::write_u16(
1208 &mut hmac_data[2..4],
1209 data_offset as u16 + attr.padded_len() as u16 - MessageHeader::LENGTH as u16,
1210 );
1211 MessageIntegritySha256::verify(&hmac_data, &key, &msg_hmac)?;
1212 return Ok(algo);
1213 }
1214 let padded_len = attr.padded_len();
1215 debug_assert!(padded_len <= data.len());
1217 data = &data[padded_len..];
1218 data_offset += padded_len;
1219 }
1220
1221 unreachable!();
1224 }
1225
1226 pub fn nth_raw_attribute(&self, atype: AttributeType, n: usize) -> Option<RawAttribute<'_>> {
1245 self.nth_raw_attribute_and_offset(atype, n)
1246 .map(|(_offset, attr)| attr)
1247 }
1248
1249 pub fn raw_attribute(&self, atype: AttributeType) -> Option<RawAttribute<'_>> {
1253 self.nth_raw_attribute(atype, 0)
1254 }
1255
1256 #[tracing::instrument(
1278 name = "message_nth_raw_attribute_and_offset",
1279 level = "trace",
1280 skip(self, atype),
1281 fields(
1282 msg.transaction = %self.transaction_id(),
1283 attribute_type = %atype,
1284 )
1285 )]
1286 pub fn nth_raw_attribute_and_offset(
1287 &self,
1288 atype: AttributeType,
1289 n: usize,
1290 ) -> Option<(usize, RawAttribute<'_>)> {
1291 if let Some((offset, attr)) = self
1292 .iter_attributes()
1293 .filter(|(_offset, attr)| attr.get_type() == atype)
1294 .nth(n)
1295 {
1296 trace!("found attribute at offset: {offset}");
1297 Some((offset, attr))
1298 } else {
1299 trace!("could not find attribute");
1300 None
1301 }
1302 }
1303
1304 pub fn raw_attribute_and_offset(
1309 &self,
1310 atype: AttributeType,
1311 ) -> Option<(usize, RawAttribute<'_>)> {
1312 self.nth_raw_attribute_and_offset(atype, 0)
1313 }
1314
1315 pub fn nth_attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1337 &'a self,
1338 n: usize,
1339 ) -> Result<A, StunParseError> {
1340 self.nth_attribute_and_offset(n).map(|(_offset, attr)| attr)
1341 }
1342
1343 pub fn attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1347 &'a self,
1348 ) -> Result<A, StunParseError> {
1349 self.nth_attribute(0)
1350 }
1351
1352 pub fn nth_attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1378 &'a self,
1379 n: usize,
1380 ) -> Result<(usize, A), StunParseError> {
1381 self.nth_raw_attribute_and_offset(A::TYPE, n)
1382 .ok_or(StunParseError::MissingAttribute(A::TYPE))
1383 .and_then(|(offset, raw)| A::from_raw(raw).map(|attr| (offset, attr)))
1384 }
1385
1386 pub fn attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1391 &'a self,
1392 ) -> Result<(usize, A), StunParseError> {
1393 self.nth_attribute_and_offset(0)
1394 }
1395
1396 pub fn iter_attributes(&self) -> impl Iterator<Item = (usize, RawAttribute<'_>)> {
1398 MessageAttributesIter::new(self.data)
1399 }
1400
1401 #[tracing::instrument(
1449 level = "trace",
1450 skip(msg, write),
1451 fields(
1452 msg.transaction = %msg.transaction_id(),
1453 )
1454 )]
1455 pub fn check_attribute_types<B: MessageWrite>(
1456 msg: &Message,
1457 supported: &[AttributeType],
1458 required_in_msg: &[AttributeType],
1459 write: B,
1460 ) -> Option<B> {
1461 let unsupported: Vec<AttributeType> = msg
1463 .iter_attributes()
1464 .map(|(_offset, a)| a.get_type())
1465 .filter(|at| at.comprehension_required() && !supported.contains(at))
1467 .collect();
1468 if !unsupported.is_empty() {
1469 warn!(
1470 "Message contains unknown comprehension required attributes {:?}, returning unknown attributes",
1471 unsupported
1472 );
1473 return Some(Message::unknown_attributes(msg, &unsupported, write));
1474 }
1475 let has_required_attribute_missing = required_in_msg
1476 .iter()
1477 .any(|&at| {
1479 !msg.iter_attributes()
1480 .map(|(_offset, a)| a.get_type())
1481 .any(|a| a == at)
1482 });
1483 if has_required_attribute_missing {
1484 warn!("Message is missing required attributes, returning bad request");
1485 return Some(Message::bad_request(msg, write));
1486 }
1487 None
1488 }
1489
1490 pub fn unknown_attributes<B: MessageWrite>(
1511 src: &Message,
1512 attributes: &[AttributeType],
1513 write: B,
1514 ) -> B {
1515 let mut out = Message::builder_error(src, write);
1516 let software = Software::new("stun-types").unwrap();
1517 out.add_attribute(&software).unwrap();
1518 let error = ErrorCode::new(420, "Unknown Attributes").unwrap();
1519 out.add_attribute(&error).unwrap();
1520 let unknown = UnknownAttributes::new(attributes);
1521 if !attributes.is_empty() {
1522 out.add_attribute(&unknown).unwrap();
1523 }
1524 out
1525 }
1526
1527 pub fn bad_request<B: MessageWrite>(src: &Message, write: B) -> B {
1545 let mut out = Message::builder_error(src, write);
1546 let software = Software::new("stun-types").unwrap();
1547 out.add_attribute(&software).unwrap();
1548 let error = ErrorCode::new(400, "Bad Request").unwrap();
1549 out.add_attribute(&error).unwrap();
1550 out
1551 }
1552
1553 pub fn has_attribute(&self, atype: AttributeType) -> bool {
1569 self.iter_attributes()
1570 .any(|(_offset, attr)| attr.get_type() == atype)
1571 }
1572}
1573impl<'a> TryFrom<&'a [u8]> for Message<'a> {
1574 type Error = StunParseError;
1575
1576 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
1577 Message::from_bytes(value)
1578 }
1579}
1580
1581#[derive(Debug)]
1582struct MessageRawAttributesIter<'a> {
1583 data: &'a [u8],
1584 data_i: usize,
1585}
1586
1587impl<'a> MessageRawAttributesIter<'a> {
1588 fn new(data: &'a [u8]) -> Self {
1589 Self {
1590 data,
1591 data_i: MessageHeader::LENGTH,
1592 }
1593 }
1594}
1595
1596impl<'a> Iterator for MessageRawAttributesIter<'a> {
1597 type Item = Result<(usize, RawAttribute<'a>), StunParseError>;
1598
1599 fn next(&mut self) -> Option<Self::Item> {
1600 if self.data_i >= self.data.len() {
1601 return None;
1602 }
1603
1604 match RawAttribute::from_bytes(&self.data[self.data_i..]) {
1605 Ok(attr) => {
1606 let padded_len = attr.padded_len();
1607 self.data_i += padded_len;
1608 if self.data_i > self.data.len() {
1609 warn!(
1610 "attribute {} extends past the end of the data",
1611 attr.get_type()
1612 );
1613 return Some(Err(StunParseError::Truncated {
1614 expected: self.data_i,
1615 actual: self.data.len(),
1616 }));
1617 }
1618 Some(Ok((self.data_i - padded_len, attr)))
1619 }
1620 Err(e) => {
1621 let offset = self.data_i;
1622 self.data_i = self.data.len();
1623 let e = match e {
1624 StunParseError::Truncated { expected, actual } => StunParseError::Truncated {
1625 expected: expected + 4 + offset,
1626 actual: actual + 4 + offset,
1627 },
1628 StunParseError::TooLarge { expected, actual } => StunParseError::TooLarge {
1629 expected: expected + 4 + offset,
1630 actual: actual + 4 + offset,
1631 },
1632 e => e,
1633 };
1634 Some(Err(e))
1635 }
1636 }
1637 }
1638}
1639
1640#[doc(hidden)]
1641#[derive(Debug)]
1642pub struct MessageAttributesIter<'a> {
1643 header_parsed: bool,
1644 inner: MessageRawAttributesIter<'a>,
1645 last_attr_type: AttributeType,
1646 seen_message_integrity: bool,
1647}
1648
1649impl<'a> MessageAttributesIter<'a> {
1650 pub fn new(data: &'a [u8]) -> Self {
1654 Self {
1655 header_parsed: false,
1656 inner: MessageRawAttributesIter::new(data),
1657 seen_message_integrity: false,
1658 last_attr_type: AttributeType::new(0),
1659 }
1660 }
1661}
1662
1663impl<'a> Iterator for MessageAttributesIter<'a> {
1664 type Item = (usize, RawAttribute<'a>);
1665
1666 fn next(&mut self) -> Option<Self::Item> {
1667 if self.last_attr_type == Fingerprint::TYPE {
1669 return None;
1670 }
1671
1672 if !self.header_parsed {
1673 let Ok(hdr) = MessageHeader::from_bytes(self.inner.data) else {
1674 self.last_attr_type = Fingerprint::TYPE;
1675 return None;
1676 };
1677 if hdr.data_length() as usize + MessageHeader::LENGTH > self.inner.data.len() {
1678 self.last_attr_type = Fingerprint::TYPE;
1679 return None;
1680 }
1681 self.header_parsed = true;
1682 }
1683
1684 let (offset, attr) = self.inner.next()?.ok()?;
1685 let attr_type = attr.get_type();
1686 if self.seen_message_integrity {
1687 if self.last_attr_type != Fingerprint::TYPE && attr_type == Fingerprint::TYPE {
1688 self.last_attr_type = attr_type;
1689 return Some((offset, attr));
1690 }
1691 if self.last_attr_type == MessageIntegrity::TYPE
1692 && attr_type == MessageIntegritySha256::TYPE
1693 {
1694 self.last_attr_type = attr_type;
1695 return Some((offset, attr));
1696 }
1697 self.last_attr_type = Fingerprint::TYPE;
1698 return None;
1699 }
1700 if attr.get_type() == MessageIntegrity::TYPE
1701 || attr.get_type() == MessageIntegritySha256::TYPE
1702 || attr.get_type() == Fingerprint::TYPE
1703 {
1704 self.seen_message_integrity = true;
1705 }
1706 self.last_attr_type = attr.get_type();
1707
1708 Some((offset, attr))
1709 }
1710}
1711
1712#[allow(clippy::len_without_is_empty)]
1713pub trait MessageWrite {
1715 type Output;
1717 fn max_size(&self) -> Option<usize> {
1720 None
1721 }
1722
1723 fn mut_data(&mut self) -> &mut [u8];
1725 fn data(&self) -> &[u8];
1727 fn len(&self) -> usize;
1729 fn push_data(&mut self, data: &[u8]);
1731 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite);
1733
1734 fn has_attribute(&self, atype: AttributeType) -> bool;
1736
1737 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType>;
1740
1741 fn finish(self) -> Self::Output;
1743}
1744
1745pub trait MessageWriteExt: MessageWrite {
1747 fn get_type(&self) -> MessageType {
1759 MessageType::from_bytes(self.data()).unwrap()
1760 }
1761
1762 fn class(&self) -> MessageClass {
1774 self.get_type().class()
1775 }
1776
1777 fn has_class(&self, cls: MessageClass) -> bool {
1789 self.class() == cls
1790 }
1791
1792 fn is_response(&self) -> bool {
1814 self.class().is_response()
1815 }
1816
1817 fn method(&self) -> Method {
1829 self.get_type().method()
1830 }
1831
1832 fn has_method(&self, method: Method) -> bool {
1845 self.method() == method
1846 }
1847
1848 fn transaction_id(&self) -> TransactionId {
1862 BigEndian::read_u128(&self.data()[4..]).into()
1863 }
1864
1865 #[tracing::instrument(
1900 name = "message_add_integrity",
1901 level = "trace",
1902 err,
1903 skip(self),
1904 fields(
1905 msg.transaction = %self.transaction_id(),
1906 )
1907 )]
1908 fn add_message_integrity(
1909 &mut self,
1910 credentials: &MessageIntegrityCredentials,
1911 algorithm: IntegrityAlgorithm,
1912 ) -> Result<(), StunWriteError> {
1913 let mut atypes = [AttributeType::new(0); 3];
1914 let mut i = 0;
1915 atypes[i] = match algorithm {
1916 IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
1917 IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
1918 };
1919 i += 1;
1920 if algorithm == IntegrityAlgorithm::Sha1 {
1921 atypes[i] = MessageIntegritySha256::TYPE;
1922 i += 1;
1923 }
1924 atypes[i] = Fingerprint::TYPE;
1925 i += 1;
1926
1927 match self.has_any_attribute(&atypes[..i]) {
1928 Some(MessageIntegrity::TYPE) => {
1930 return Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
1931 }
1932 Some(MessageIntegritySha256::TYPE) => {
1933 return Err(StunWriteError::AttributeExists(
1934 MessageIntegritySha256::TYPE,
1935 ));
1936 }
1937 Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
1938 _ => (),
1939 }
1940 match algorithm {
1941 IntegrityAlgorithm::Sha1 => {
1942 check_attribute_can_fit(self, &MessageIntegrity::new([0; 20]))?
1943 }
1944 IntegrityAlgorithm::Sha256 => {
1945 check_attribute_can_fit(self, &MessageIntegritySha256::new(&[0; 32]).unwrap())?
1946 }
1947 };
1948
1949 add_message_integrity_unchecked(self, credentials, algorithm);
1950
1951 Ok(())
1952 }
1953
1954 #[tracing::instrument(
1972 name = "message_add_fingerprint",
1973 level = "trace",
1974 skip(self),
1975 fields(
1976 msg.transaction = %self.transaction_id(),
1977 )
1978 )]
1979 fn add_fingerprint(&mut self) -> Result<(), StunWriteError> {
1980 if self.has_attribute(Fingerprint::TYPE) {
1981 return Err(StunWriteError::AttributeExists(Fingerprint::TYPE));
1982 }
1983
1984 check_attribute_can_fit(self, &Fingerprint::new([0; 4]))?;
1985 add_fingerprint_unchecked(self);
1986
1987 Ok(())
1988 }
1989
1990 #[tracing::instrument(
2021 name = "message_add_attribute",
2022 level = "trace",
2023 err,
2024 skip(self, attr),
2025 fields(
2026 msg.transaction = %self.transaction_id(),
2027 )
2028 )]
2029 fn add_attribute(&mut self, attr: &dyn AttributeWrite) -> Result<(), StunWriteError> {
2030 let ty = attr.get_type();
2031 match ty {
2032 MessageIntegrity::TYPE => {
2033 panic!("Cannot write MessageIntegrity with `add_attribute`. Use add_message_integrity() instead");
2034 }
2035 MessageIntegritySha256::TYPE => {
2036 panic!("Cannot write MessageIntegritySha256 with `add_attribute`. Use add_message_integrity() instead");
2037 }
2038 Fingerprint::TYPE => {
2039 panic!(
2040 "Cannot write Fingerprint with `add_attribute`. Use add_fingerprint() instead"
2041 );
2042 }
2043 _ => (),
2044 }
2045 match self.has_any_attribute(&[
2046 MessageIntegrity::TYPE,
2047 MessageIntegritySha256::TYPE,
2048 Fingerprint::TYPE,
2049 ]) {
2050 Some(MessageIntegrity::TYPE) => return Err(StunWriteError::MessageIntegrityExists),
2052 Some(MessageIntegritySha256::TYPE) => {
2053 return Err(StunWriteError::MessageIntegrityExists)
2054 }
2055 Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2056 _ => (),
2057 }
2058 check_attribute_can_fit(self, attr)?;
2059 self.push_attribute_unchecked(attr);
2060 Ok(())
2061 }
2062}
2063
2064impl<T: MessageWrite> MessageWriteExt for T {}
2065
2066#[derive(Debug, Default)]
2068pub struct MessageWriteVec {
2069 output: Vec<u8>,
2070 attributes: smallvec::SmallVec<[AttributeType; 16]>,
2071}
2072
2073impl MessageWriteVec {
2074 pub fn new() -> Self {
2076 Self::default()
2077 }
2078
2079 pub fn with_capacity(capacity: usize) -> Self {
2081 Self {
2082 output: Vec::with_capacity(capacity),
2083 attributes: Default::default(),
2084 }
2085 }
2086}
2087
2088impl core::ops::Deref for MessageWriteVec {
2089 type Target = Vec<u8>;
2090 fn deref(&self) -> &Self::Target {
2091 &self.output
2092 }
2093}
2094
2095impl core::ops::DerefMut for MessageWriteVec {
2096 fn deref_mut(&mut self) -> &mut Self::Target {
2097 &mut self.output
2098 }
2099}
2100
2101impl MessageWrite for MessageWriteVec {
2102 type Output = Vec<u8>;
2103
2104 fn mut_data(&mut self) -> &mut [u8] {
2105 &mut self.output
2106 }
2107
2108 fn data(&self) -> &[u8] {
2109 &self.output
2110 }
2111
2112 fn len(&self) -> usize {
2113 self.output.len()
2114 }
2115
2116 fn push_data(&mut self, data: &[u8]) {
2117 self.output.extend(data)
2118 }
2119
2120 fn finish(self) -> Self::Output {
2121 self.output
2122 }
2123
2124 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2125 let offset = self.output.len();
2126 let padded_len = attr.padded_len();
2127 let expected = offset + padded_len;
2128 BigEndian::write_u16(
2129 &mut self.output[2..4],
2130 (expected - MessageHeader::LENGTH) as u16,
2131 );
2132 self.output.resize(expected, 0);
2133 attr.write_into_unchecked(&mut self.output[offset..]);
2134 self.attributes.push(attr.get_type());
2135 }
2136
2137 fn has_attribute(&self, atype: AttributeType) -> bool {
2138 self.attributes.contains(&atype)
2139 }
2140
2141 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2142 self.attributes
2143 .iter()
2144 .find(|&typ| atypes.contains(typ))
2145 .cloned()
2146 }
2147}
2148
2149#[derive(Debug, Default)]
2151pub struct MessageWriteMutSlice<'a> {
2152 output: &'a mut [u8],
2153 offset: usize,
2154 attributes: smallvec::SmallVec<[AttributeType; 16]>,
2155}
2156
2157impl<'a> MessageWriteMutSlice<'a> {
2158 pub fn new(data: &'a mut [u8]) -> Self {
2160 Self {
2161 output: data,
2162 offset: 0,
2163 attributes: Default::default(),
2164 }
2165 }
2166}
2167
2168impl core::ops::Deref for MessageWriteMutSlice<'_> {
2169 type Target = [u8];
2170 fn deref(&self) -> &Self::Target {
2171 self.output
2172 }
2173}
2174
2175impl core::ops::DerefMut for MessageWriteMutSlice<'_> {
2176 fn deref_mut(&mut self) -> &mut Self::Target {
2177 self.output
2178 }
2179}
2180
2181impl<'a> MessageWrite for MessageWriteMutSlice<'a> {
2182 type Output = usize;
2183
2184 fn max_size(&self) -> Option<usize> {
2185 Some(self.output.len())
2186 }
2187
2188 fn mut_data(&mut self) -> &mut [u8] {
2189 &mut self.output[..self.offset]
2190 }
2191
2192 fn data(&self) -> &[u8] {
2193 &self.output[..self.offset]
2194 }
2195
2196 fn len(&self) -> usize {
2197 self.offset
2198 }
2199
2200 fn push_data(&mut self, data: &[u8]) {
2201 let len = data.len();
2202 self.output[self.offset..self.offset + len].copy_from_slice(data);
2203 self.offset += len;
2204 }
2205
2206 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2207 let padded_len = attr.padded_len();
2208 let expected = self.offset + padded_len;
2209 BigEndian::write_u16(
2210 &mut self.output[2..4],
2211 (expected - MessageHeader::LENGTH) as u16,
2212 );
2213 self.attributes.push(attr.get_type());
2214 attr.write_into(&mut self.output[self.offset..self.offset + padded_len])
2215 .unwrap();
2216 self.offset += padded_len;
2217 }
2218
2219 fn finish(self) -> Self::Output {
2220 self.offset
2221 }
2222
2223 fn has_attribute(&self, atype: AttributeType) -> bool {
2224 self.attributes.contains(&atype)
2225 }
2226
2227 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2228 self.attributes
2229 .iter()
2230 .find(|&typ| atypes.contains(typ))
2231 .cloned()
2232 }
2233}
2234
2235fn check_attribute_can_fit<O, T: MessageWrite<Output = O> + ?Sized>(
2236 this: &mut T,
2237 attr: &dyn AttributeWrite,
2238) -> Result<usize, StunWriteError> {
2239 let len = attr.padded_len();
2240 let out_data = this.data();
2241 if out_data.len() < MessageHeader::LENGTH {
2242 return Err(StunWriteError::TooSmall {
2243 expected: 20,
2244 actual: out_data.len(),
2245 });
2246 }
2247 let expected = BigEndian::read_u16(&out_data[2..4]) as usize + MessageHeader::LENGTH + len;
2248 if let Some(max) = this.max_size() {
2249 if max < expected {
2250 return Err(StunWriteError::TooSmall {
2251 expected,
2252 actual: max,
2253 });
2254 }
2255 }
2256 Ok(expected)
2257}
2258
2259fn add_message_integrity_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(
2260 this: &mut T,
2261 credentials: &MessageIntegrityCredentials,
2262 algorithm: IntegrityAlgorithm,
2263) {
2264 let key = credentials.make_hmac_key();
2265 match algorithm {
2268 IntegrityAlgorithm::Sha1 => {
2269 this.push_attribute_unchecked(&MessageIntegrity::new([0; 20]));
2270 let len = this.len();
2271 let data = this.mut_data();
2272 let integrity = MessageIntegrity::compute(&data[..len - 24], &key).unwrap();
2273 data[len - 20..].copy_from_slice(&integrity);
2274 }
2275 IntegrityAlgorithm::Sha256 => {
2276 this.push_attribute_unchecked(&MessageIntegritySha256::new(&[0; 32]).unwrap());
2277 let len = this.len();
2278 let data = this.mut_data();
2279 let integrity = MessageIntegritySha256::compute(&data[..len - 36], &key).unwrap();
2280 data[len - 32..].copy_from_slice(&integrity);
2281 }
2282 }
2283}
2284
2285fn add_fingerprint_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(this: &mut T) {
2286 this.push_attribute_unchecked(&Fingerprint::new([0; 4]));
2289 let len = this.len();
2290 let data = this.mut_data();
2291 let fingerprint = Fingerprint::compute(&data[..len - 8]);
2292 let fingerprint = Fingerprint::new(fingerprint);
2293 fingerprint.write_into(&mut data[len - 8..]).unwrap();
2294}
2295
2296#[cfg(test)]
2297mod tests {
2298 use alloc::borrow::ToOwned;
2299 use tracing::error;
2300
2301 use super::*;
2302
2303 #[test]
2304 #[should_panic(expected = "Method value is out of range")]
2305 fn method_value_out_of_range() {
2306 let _log = crate::tests::test_init_log();
2307 Method::new(0xf000);
2308 }
2309
2310 #[test]
2311 #[cfg(feature = "std")]
2312 fn method_name() {
2313 let _log = crate::tests::test_init_log();
2314 assert_eq!(BINDING.name(), "BINDING");
2315 let method = Method::new(0x111);
2316 method.add_name("SOME-NAME");
2317 assert_eq!(method.name(), "SOME-NAME");
2318 assert_eq!(Method::new(0x112).name(), "unknown");
2319 }
2320
2321 #[test]
2322 fn msg_type_roundtrip() {
2323 let _log = crate::tests::test_init_log();
2324 for m in 0..0xfff {
2326 let m = Method::new(m);
2327 let classes = vec![
2328 MessageClass::Request,
2329 MessageClass::Indication,
2330 MessageClass::Success,
2331 MessageClass::Error,
2332 ];
2333 for c in classes {
2334 let mtype = MessageType::from_class_method(c, m);
2335 trace!("{mtype}");
2336 assert_eq!(mtype.class(), c);
2337 assert_eq!(mtype.method(), m);
2338 let bytes = mtype.to_bytes();
2339 let ptype = MessageType::from_bytes(&bytes).unwrap();
2340 assert_eq!(mtype, ptype);
2341 }
2342 }
2343 }
2344
2345 #[test]
2346 fn msg_type_not_stun() {
2347 assert!(matches!(
2348 MessageType::from_bytes(&[0xc0, 0x00]),
2349 Err(StunParseError::NotStun)
2350 ));
2351 }
2352
2353 #[test]
2354 fn msg_roundtrip() {
2355 let _log = crate::tests::test_init_log();
2356 for m in (0x009..0x4ff).step_by(0x123) {
2358 let m = Method::new(m);
2359 let classes = vec![
2360 MessageClass::Request,
2361 MessageClass::Indication,
2362 MessageClass::Success,
2363 MessageClass::Error,
2364 ];
2365 for c in classes {
2366 let mtype = MessageType::from_class_method(c, m);
2367 for tid in (0x18..0xff_ffff_ffff_ffff_ffff).step_by(0xfedc_ba98_7654_3210) {
2368 let mut msg = Message::builder(mtype, tid.into(), MessageWriteVec::default());
2369 let attr = RawAttribute::new(1.into(), &[3]);
2370 assert!(msg.add_attribute(&attr).is_ok());
2371 let data = msg.finish();
2372
2373 let msg = Message::from_bytes(&data).unwrap();
2374 let msg_attr = msg.raw_attribute(1.into()).unwrap();
2375 assert_eq!(msg_attr, attr);
2376 assert_eq!(msg.get_type(), mtype);
2377 assert_eq!(msg.transaction_id(), tid.into());
2378 }
2379 }
2380 }
2381 }
2382
2383 #[test]
2384 fn unknown_attributes() {
2385 let _log = crate::tests::test_init_log();
2386 let src = Message::builder_request(BINDING, MessageWriteVec::default()).finish();
2387 let src = Message::from_bytes(&src).unwrap();
2388 let msg =
2389 Message::unknown_attributes(&src, &[Software::TYPE], MessageWriteVec::new()).finish();
2390 let msg = Message::from_bytes(&msg).unwrap();
2391 assert_eq!(msg.transaction_id(), src.transaction_id());
2392 assert_eq!(msg.class(), MessageClass::Error);
2393 assert_eq!(msg.method(), src.method());
2394 let err = msg.attribute::<ErrorCode>().unwrap();
2395 assert_eq!(err.code(), 420);
2396 let unknown_attrs = msg.attribute::<UnknownAttributes>().unwrap();
2397 assert!(unknown_attrs.has_attribute(Software::TYPE));
2398 }
2399
2400 #[test]
2401 fn bad_request() {
2402 let _log = crate::tests::test_init_log();
2403 let src = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2404 let src = Message::from_bytes(&src).unwrap();
2405 let msg = Message::bad_request(&src, MessageWriteVec::new()).finish();
2406 let msg = Message::from_bytes(&msg).unwrap();
2407 assert_eq!(msg.transaction_id(), src.transaction_id());
2408 assert_eq!(msg.class(), MessageClass::Error);
2409 assert_eq!(msg.method(), src.method());
2410 let err = msg.attribute::<ErrorCode>().unwrap();
2411 assert_eq!(err.code(), 400);
2412 }
2413
2414 #[test]
2415 fn fingerprint() {
2416 let _log = crate::tests::test_init_log();
2417 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2418 let software = Software::new("s").unwrap();
2419 msg.add_attribute(&software).unwrap();
2420 msg.add_fingerprint().unwrap();
2421 let bytes = msg.finish();
2422 let new_msg = Message::from_bytes(&bytes).unwrap();
2424 let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2425 assert_eq!(software.software(), "s");
2426 assert_eq!(offset, 20);
2427 let (offset, _new_fingerprint) = new_msg.attribute_and_offset::<Fingerprint>().unwrap();
2428 assert_eq!(offset, 28);
2429 }
2430
2431 #[test]
2432 fn integrity() {
2433 let _log = crate::tests::test_init_log();
2434 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2435 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2436 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2437 let software = Software::new("s").unwrap();
2438 msg.add_attribute(&software).unwrap();
2439 msg.add_message_integrity(&credentials, algorithm).unwrap();
2440 let bytes = msg.finish();
2441 let new_msg = Message::from_bytes(&bytes).unwrap();
2443 new_msg.validate_integrity(&credentials).unwrap();
2444 let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2445 assert_eq!(software.software(), "s");
2446 assert_eq!(offset, 20);
2447 }
2448 }
2449
2450 #[test]
2451 fn write_into_short_destination() {
2452 let _log = crate::tests::test_init_log();
2453 const LEN: usize = MessageHeader::LENGTH + 8;
2454 let mut data = [0; LEN - 1];
2455 let mut msg = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
2456 let software = Software::new("s").unwrap();
2457 assert!(
2458 matches!(msg.add_attribute(&software), Err(StunWriteError::TooSmall { expected, actual }) if expected == LEN && actual == LEN - 1)
2459 );
2460 }
2461
2462 #[test]
2463 fn add_duplicate_integrity() {
2464 let _log = crate::tests::test_init_log();
2465 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2466 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2467 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
2468 .unwrap();
2469 assert!(matches!(
2470 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2471 Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2472 ));
2473 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2474 .unwrap();
2475 assert!(matches!(
2476 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256),
2477 Err(StunWriteError::AttributeExists(
2478 MessageIntegritySha256::TYPE
2479 ))
2480 ));
2481 let software = Software::new("s").unwrap();
2482 assert!(matches!(
2483 msg.add_attribute(&software),
2484 Err(StunWriteError::MessageIntegrityExists)
2485 ));
2486 }
2487
2488 #[test]
2489 fn add_sha1_integrity_after_sha256() {
2490 let _log = crate::tests::test_init_log();
2491 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2492 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2493 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2494 .unwrap();
2495 assert!(matches!(
2496 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2497 Err(StunWriteError::AttributeExists(
2498 MessageIntegritySha256::TYPE
2499 ))
2500 ));
2501 }
2502
2503 #[test]
2504 fn add_attribute_after_integrity() {
2505 let _log = crate::tests::test_init_log();
2506 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2507 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2508 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2509 msg.add_message_integrity(&credentials, algorithm).unwrap();
2510 let software = Software::new("s").unwrap();
2511 assert!(matches!(
2512 msg.add_attribute(&software),
2513 Err(StunWriteError::MessageIntegrityExists)
2514 ));
2515 }
2516 }
2517
2518 #[test]
2519 fn add_raw_attribute_after_integrity() {
2520 let _log = crate::tests::test_init_log();
2521 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2522 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2523 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2524 msg.add_message_integrity(&credentials, algorithm).unwrap();
2525 let software = Software::new("s").unwrap();
2526 let raw = software.to_raw();
2527 assert!(matches!(
2528 msg.add_attribute(&raw),
2529 Err(StunWriteError::MessageIntegrityExists)
2530 ));
2531 }
2532 }
2533
2534 #[test]
2535 fn add_integrity_after_fingerprint() {
2536 let _log = crate::tests::test_init_log();
2537 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2538 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2539 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2540 msg.add_fingerprint().unwrap();
2541 assert!(matches!(
2542 msg.add_message_integrity(&credentials, algorithm),
2543 Err(StunWriteError::FingerprintExists)
2544 ));
2545 }
2546 }
2547
2548 #[test]
2549 fn duplicate_fingerprint() {
2550 let _log = crate::tests::test_init_log();
2551 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2552 msg.add_fingerprint().unwrap();
2553 assert!(matches!(
2554 msg.add_fingerprint(),
2555 Err(StunWriteError::AttributeExists(Fingerprint::TYPE))
2556 ));
2557 }
2558
2559 #[test]
2560 fn parse_invalid_fingerprint() {
2561 let _log = crate::tests::test_init_log();
2562 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2563 msg.add_fingerprint().unwrap();
2564 let mut bytes = msg.finish();
2565 bytes[24] = 0x80;
2566 bytes[25] = 0x80;
2567 bytes[26] = 0x80;
2568 bytes[27] = 0x80;
2569 assert!(matches!(
2570 Message::from_bytes(&bytes),
2571 Err(StunParseError::FingerprintMismatch)
2572 ));
2573 }
2574
2575 #[test]
2576 fn parse_wrong_magic() {
2577 let _log = crate::tests::test_init_log();
2578 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2579 msg.add_fingerprint().unwrap();
2580 let mut bytes = msg.finish();
2581 bytes[4] = 0x80;
2582 assert!(matches!(
2583 Message::from_bytes(&bytes),
2584 Err(StunParseError::NotStun)
2585 ));
2586 }
2587
2588 #[test]
2589 fn parse_attribute_after_integrity() {
2590 let _log = crate::tests::test_init_log();
2591 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2592 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2593 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2594 msg.add_message_integrity(&credentials, algorithm).unwrap();
2595 let mut bytes = msg.finish();
2596 let software = Software::new("s").unwrap();
2597 let software_bytes = RawAttribute::from(&software).to_bytes();
2598 let software_len = software_bytes.len();
2599 bytes.extend(software_bytes);
2600 bytes[3] += software_len as u8;
2601 let msg = Message::from_bytes(&bytes).unwrap();
2602 assert!(msg.raw_attribute(Software::TYPE).is_none());
2603 }
2604 }
2605
2606 #[test]
2607 fn parse_duplicate_integrity_after_integrity() {
2608 let _log = crate::tests::test_init_log();
2609 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2610 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2611 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2612 msg.add_message_integrity(&credentials, algorithm).unwrap();
2613 add_message_integrity_unchecked(&mut msg, &credentials, algorithm);
2615 let bytes = msg.finish();
2616 let integrity_type = match algorithm {
2617 IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2618 IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2619 };
2620 let msg = Message::from_bytes(&bytes).unwrap();
2621 msg.nth_raw_attribute(integrity_type, 0).unwrap();
2622 assert!(msg.nth_raw_attribute(integrity_type, 1).is_none());
2623 }
2624 }
2625
2626 #[test]
2627 fn parse_attribute_after_fingerprint() {
2628 let _log = crate::tests::test_init_log();
2629 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2630 msg.add_fingerprint().unwrap();
2631 let mut bytes = msg.finish();
2632 let software = Software::new("s").unwrap();
2633 let software_bytes = RawAttribute::from(&software).to_bytes();
2634 let software_len = software_bytes.len();
2635 bytes.extend(software_bytes);
2636 bytes[3] += software_len as u8;
2637 let msg = Message::from_bytes(&bytes).unwrap();
2638 assert!(msg.raw_attribute(Fingerprint::TYPE).is_some());
2639 assert!(msg.raw_attribute(Software::TYPE).is_none());
2640 }
2641
2642 #[test]
2643 fn parse_duplicate_fingerprint_after_fingerprint() {
2644 let _log = crate::tests::test_init_log();
2645 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2646 msg.add_fingerprint().unwrap();
2647 add_fingerprint_unchecked(&mut msg);
2648 let bytes = msg.finish();
2649 let msg = Message::from_bytes(&bytes).unwrap();
2650 assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 0).is_some());
2651 assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 1).is_none());
2652 }
2653
2654 #[test]
2655 fn add_attribute_after_fingerprint() {
2656 let _log = crate::tests::test_init_log();
2657 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2658 msg.add_fingerprint().unwrap();
2659 let software = Software::new("s").unwrap();
2660 assert!(matches!(
2661 msg.add_attribute(&software),
2662 Err(StunWriteError::FingerprintExists)
2663 ));
2664 }
2665
2666 #[test]
2667 fn add_raw_attribute_after_fingerprint() {
2668 let _log = crate::tests::test_init_log();
2669 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2670 msg.add_fingerprint().unwrap();
2671 let software = Software::new("s").unwrap();
2672 let raw = software.to_raw();
2673 assert!(matches!(
2674 msg.add_attribute(&raw),
2675 Err(StunWriteError::FingerprintExists)
2676 ));
2677 }
2678
2679 #[test]
2680 fn parse_truncated_message_header() {
2681 let _log = crate::tests::test_init_log();
2682 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2683 msg.add_fingerprint().unwrap();
2684 let bytes = msg.finish();
2685 assert!(matches!(
2686 Message::from_bytes(&bytes[..8]),
2687 Err(StunParseError::Truncated {
2688 expected: 20,
2689 actual: 8
2690 })
2691 ));
2692 }
2693
2694 #[test]
2695 fn parse_truncated_message() {
2696 let _log = crate::tests::test_init_log();
2697 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2698 msg.add_fingerprint().unwrap();
2699 let bytes = msg.finish();
2700 assert!(matches!(
2701 Message::from_bytes(&bytes[..24]),
2702 Err(StunParseError::Truncated {
2703 expected: 28,
2704 actual: 24
2705 })
2706 ));
2707 }
2708
2709 #[test]
2710 fn parse_truncated_message_attribute() {
2711 let _log = crate::tests::test_init_log();
2712 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2713 msg.add_fingerprint().unwrap();
2714 let mut bytes = msg.finish();
2715 bytes[3] = 4;
2717 assert!(matches!(
2718 Message::from_bytes(&bytes[..24]),
2719 Err(StunParseError::Truncated {
2720 expected: 28,
2721 actual: 24
2722 })
2723 ));
2724 }
2725
2726 #[test]
2727 fn parse_attribute_extends_past_message_end() {
2728 let _log = crate::tests::test_init_log();
2729 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2730 msg.add_attribute(&Software::new("a").unwrap()).unwrap();
2731 msg[23] += 1;
2732 let mut bytes = msg.finish();
2733 bytes[3] -= 1;
2734 error!("{bytes:x?}");
2735 error!("{:?}", Message::from_bytes(&bytes[..27]));
2736 assert!(matches!(
2737 Message::from_bytes(&bytes[..27]),
2738 Err(StunParseError::Truncated {
2739 expected: 28,
2740 actual: 27
2741 })
2742 ));
2743 }
2744
2745 #[test]
2746 fn valid_attributes() {
2747 let _log = crate::tests::test_init_log();
2748 let mut src = Message::builder_request(BINDING, MessageWriteVec::new());
2749 let username = Username::new("123").unwrap();
2750 src.add_attribute(&username).unwrap();
2751 let nonce = Nonce::new("nonce").unwrap();
2752 src.add_attribute(&nonce).unwrap();
2753 let src = src.finish();
2754 let src = Message::from_bytes(&src).unwrap();
2755
2756 let res = Message::check_attribute_types(
2758 &src,
2759 &[Username::TYPE, Nonce::TYPE],
2760 &[Username::TYPE],
2761 MessageWriteVec::new(),
2762 );
2763 assert!(res.is_none());
2764
2765 let res = Message::check_attribute_types(
2767 &src,
2768 &[Username::TYPE, Nonce::TYPE],
2769 &[Fingerprint::TYPE],
2770 MessageWriteVec::new(),
2771 );
2772 assert!(res.is_some());
2773 let res = res.unwrap();
2774 let res = res.finish();
2775 let res = Message::from_bytes(&res).unwrap();
2776 assert!(res.has_class(MessageClass::Error));
2777 assert!(res.has_method(src.method()));
2778 let err = res.attribute::<ErrorCode>().unwrap();
2779 assert_eq!(err.code(), 400);
2780
2781 let res =
2783 Message::check_attribute_types(&src, &[Username::TYPE], &[], MessageWriteVec::new());
2784 assert!(res.is_some());
2785 let res = res.unwrap();
2786 let data = res.finish();
2787 let res = Message::from_bytes(&data).unwrap();
2788 assert!(res.has_class(MessageClass::Error));
2789 assert!(res.has_method(src.method()));
2790 let err = res.attribute::<ErrorCode>().unwrap();
2791 assert_eq!(err.code(), 420);
2792 let unknown = res.attribute::<UnknownAttributes>().unwrap();
2793 assert!(unknown.has_attribute(Nonce::TYPE));
2794 }
2795
2796 #[test]
2797 fn attributes_iter_with_short_data() {
2798 let _log = crate::tests::test_init_log();
2799 assert_eq!(
2800 MessageAttributesIter::new(&[0x0, 0x1, 0x2, 0x3, 0x4]).next(),
2801 None
2802 );
2803 assert_eq!(
2804 MessageAttributesIter::new(&[
2805 0x0, 0x1, 0x2, 0x3, 0x21, 0x12, 0xa4, 0x42, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
2806 0x10, 0x11, 0x12, 0x13, 0x14,
2807 ])
2808 .next(),
2809 None
2810 );
2811 }
2812
2813 #[test]
2814 fn attributes_iter_software_after_fingerprint_ignored() {
2815 let _log = crate::tests::test_init_log();
2816 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2817 msg.add_fingerprint().unwrap();
2818 let mut bytes = msg.finish();
2819 let software = Software::new("s").unwrap();
2820 let software_bytes = RawAttribute::from(&software).to_bytes();
2821 let software_len = software_bytes.len();
2822 bytes.extend(software_bytes);
2823 bytes[3] += software_len as u8;
2824 let mut it = MessageAttributesIter::new(&bytes);
2825 let (_offset, fingerprint) = it.next().unwrap();
2826 assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
2827 assert_eq!(it.next(), None);
2828 }
2829
2830 #[test]
2831 fn attributes_iter_message_integrities_fingerprint() {
2832 let _log = crate::tests::test_init_log();
2833 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2834 let credentials = ShortTermCredentials::new("pass".to_owned());
2835 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
2836 .unwrap();
2837 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
2838 .unwrap();
2839 msg.add_fingerprint().unwrap();
2840 let mut bytes = msg.finish();
2841 let software = Software::new("s").unwrap();
2842 let software_bytes = RawAttribute::from(&software).to_bytes();
2843 let software_len = software_bytes.len();
2844 bytes.extend(software_bytes);
2845 bytes[3] += software_len as u8;
2846 let mut it = MessageAttributesIter::new(&bytes);
2847 assert_eq!(it.next().unwrap().1.get_type(), MessageIntegrity::TYPE);
2848 assert_eq!(
2849 it.next().unwrap().1.get_type(),
2850 MessageIntegritySha256::TYPE
2851 );
2852 assert_eq!(it.next().unwrap().1.get_type(), Fingerprint::TYPE);
2853 assert_eq!(it.next(), None);
2854 }
2855
2856 #[test]
2857 fn attributes_iter_fingerprint_after_fingerprint_ignored() {
2858 let _log = crate::tests::test_init_log();
2859 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2860 msg.add_fingerprint().unwrap();
2861 let mut bytes = msg.finish();
2862 let fingerprint = Fingerprint::new([bytes[bytes.len() - 1].wrapping_sub(1); 4]);
2863 let fingerprint_bytes = RawAttribute::from(&fingerprint).to_bytes();
2864 let fingerprint_len = fingerprint_bytes.len();
2865 bytes.extend(fingerprint_bytes);
2866 bytes[3] += fingerprint_len as u8;
2867 let mut it = MessageAttributesIter::new(&bytes);
2868 let (_offset, fingerprint) = it.next().unwrap();
2869 assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
2870 assert_eq!(it.next(), None);
2871 }
2872
2873 #[test]
2874 fn write_vec_state() {
2875 let _log = crate::tests::test_init_log();
2876 let mut src = Message::builder_request(BINDING, MessageWriteVec::with_capacity(0x10));
2877 assert_eq!(src.len(), 20);
2878 assert_eq!(src[4], 0x21);
2879 let username = Username::new("123").unwrap();
2880 src.add_attribute(&username).unwrap();
2881 let nonce = Nonce::new("nonce").unwrap();
2882 src.add_attribute(&nonce).unwrap();
2883
2884 assert!(src.has_attribute(Username::TYPE));
2885 assert!(src.has_attribute(Nonce::TYPE));
2886 assert_eq!(
2887 src.has_any_attribute(&[Username::TYPE, Nonce::TYPE]),
2888 Some(Username::TYPE)
2889 );
2890 assert_eq!(
2891 src.has_any_attribute(&[Nonce::TYPE, Username::TYPE]),
2892 Some(Username::TYPE)
2893 );
2894 assert!(src.has_class(MessageClass::Request));
2895 assert!(!src.is_response());
2896 assert!(src.has_method(BINDING));
2897 assert!(!src.has_method(Method::new(0x111)));
2898 }
2899
2900 #[test]
2901 fn write_mut_slice_success() {
2902 let _log = crate::tests::test_init_log();
2903 let mut data = [0; 64];
2904 let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
2905 assert_eq!(src.len(), 20);
2906 assert_eq!(src[4], 0x21);
2907 let username = Username::new("123").unwrap();
2908 src.add_attribute(&username).unwrap();
2909 let nonce = Nonce::new("nonce").unwrap();
2910 src.add_attribute(&nonce).unwrap();
2911 assert!(src.has_attribute(Username::TYPE));
2912 assert!(!src.has_attribute(Software::TYPE));
2913 assert_eq!(src.finish(), 40);
2914 let msg = Message::from_bytes(&data[..40]).unwrap();
2915 let u2 = msg.attribute::<Username>().unwrap();
2916 assert_eq!(u2.username(), "123");
2917 let n2 = msg.attribute::<Nonce>().unwrap();
2918 assert_eq!(n2.nonce(), "nonce");
2919 }
2920
2921 #[test]
2922 fn write_mut_slice_too_short() {
2923 let _log = crate::tests::test_init_log();
2924 let mut data = [0; 20];
2925 let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
2926 assert!(matches!(
2927 src.add_attribute(&Username::new("123").unwrap()),
2928 Err(StunWriteError::TooSmall {
2929 expected: 28,
2930 actual: 20
2931 })
2932 ));
2933 }
2934
2935 #[test]
2936 #[should_panic(expected = "created from a non-request message")]
2937 fn builder_success_panic() {
2938 let _log = crate::tests::test_init_log();
2939 let msg = Message::builder(
2940 MessageType::from_class_method(MessageClass::Indication, BINDING),
2941 TransactionId::generate(),
2942 MessageWriteVec::new(),
2943 )
2944 .finish();
2945 let msg = Message::from_bytes(&msg).unwrap();
2946 let _builder = Message::builder_success(&msg, MessageWriteVec::new());
2947 }
2948
2949 #[test]
2950 #[should_panic(expected = "created from a non-request message")]
2951 fn builder_error_panic() {
2952 let _log = crate::tests::test_init_log();
2953 let msg = Message::builder(
2954 MessageType::from_class_method(MessageClass::Indication, BINDING),
2955 TransactionId::generate(),
2956 MessageWriteVec::new(),
2957 )
2958 .finish();
2959 let msg = Message::from_bytes(&msg).unwrap();
2960 let _builder = Message::builder_error(&msg, MessageWriteVec::new());
2961 }
2962
2963 #[test]
2964 #[should_panic(expected = "Use add_message_integrity() instead")]
2965 fn builder_add_attribute_integrity_panic() {
2966 let _log = crate::tests::test_init_log();
2967 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2968 let hmac = [2; 20];
2969 let integrity = MessageIntegrity::new(hmac);
2970 msg.add_attribute(&integrity).unwrap();
2971 }
2972
2973 #[test]
2974 #[should_panic(expected = "Use add_message_integrity() instead")]
2975 fn builder_add_raw_attribute_integrity_panic() {
2976 let _log = crate::tests::test_init_log();
2977 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2978 let hmac = [2; 20];
2979 let integrity = MessageIntegrity::new(hmac);
2980 let raw = integrity.to_raw();
2981 msg.add_attribute(&raw).unwrap();
2982 }
2983
2984 #[test]
2985 #[should_panic(expected = "Use add_message_integrity() instead")]
2986 fn builder_add_attribute_integrity_sha256_panic() {
2987 let _log = crate::tests::test_init_log();
2988 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2989 let hmac = [2; 16];
2990 let integrity = MessageIntegritySha256::new(&hmac).unwrap();
2991 msg.add_attribute(&integrity).unwrap();
2992 }
2993
2994 #[test]
2995 #[should_panic(expected = "Use add_message_integrity() instead")]
2996 fn builder_add_raw_attribute_integrity_sha256_panic() {
2997 let _log = crate::tests::test_init_log();
2998 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2999 let hmac = [2; 16];
3000 let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3001 let raw = integrity.to_raw();
3002 msg.add_attribute(&raw).unwrap();
3003 }
3004
3005 #[test]
3006 #[should_panic(expected = "Use add_fingerprint() instead")]
3007 fn builder_add_attribute_fingerprint_panic() {
3008 let _log = crate::tests::test_init_log();
3009 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3010 let fingerprint = [2; 4];
3011 let fingerprint = Fingerprint::new(fingerprint);
3012 msg.add_attribute(&fingerprint).unwrap();
3013 }
3014
3015 #[test]
3016 #[should_panic(expected = "Use add_fingerprint() instead")]
3017 fn builder_add_raw_attribute_fingerprint_panic() {
3018 let _log = crate::tests::test_init_log();
3019 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3020 let fingerprint = [2; 4];
3021 let fingerprint = Fingerprint::new(fingerprint);
3022 let raw = fingerprint.to_raw();
3023 msg.add_attribute(&raw).unwrap();
3024 }
3025
3026 #[test]
3027 fn rfc5769_vector1() {
3028 let _log = crate::tests::test_init_log();
3029 let data = vec![
3031 0x00, 0x01, 0x00, 0x58, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x10, 0x53, 0x54, 0x55, 0x4e, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x00, 0x24, 0x00, 0x04, 0x6e, 0x00, 0x01, 0xff, 0x80, 0x29, 0x00, 0x08, 0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36, 0x00, 0x06, 0x00, 0x09, 0x65, 0x76, 0x74, 0x6a, 0x3a, 0x68, 0x36, 0x76, 0x59, 0x20, 0x20, 0x20, 0x00, 0x08, 0x00, 0x14, 0x9a, 0xea, 0xa7, 0x0c, 0xbf, 0xd8, 0xcb, 0x56, 0x78, 0x1e, 0xf2, 0xb5, 0xb2, 0xd3, 0xf2, 0x49, 0xc1, 0xb5, 0x71, 0xa2, 0x80, 0x28, 0x00, 0x04, 0xe5, 0x7a, 0x3b, 0xcf, ];
3059 let msg = Message::from_bytes(&data).unwrap();
3060 assert!(msg.has_class(MessageClass::Request));
3061 assert!(msg.has_method(BINDING));
3062 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3063
3064 let mut builder = Message::builder(
3065 MessageType::from_class_method(MessageClass::Request, BINDING),
3066 msg.transaction_id(),
3067 MessageWriteVec::new(),
3068 );
3069
3070 assert!(msg.has_attribute(Software::TYPE));
3072 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3073 assert!(Software::try_from(&raw).is_ok());
3074 let software = Software::try_from(&raw).unwrap();
3075 assert_eq!(software.software(), "STUN test client");
3076 builder.add_attribute(&software).unwrap();
3077
3078 builder
3080 .add_attribute(&RawAttribute::new(0x24.into(), &[0x6e, 0x00, 0x01, 0xff]))
3081 .unwrap();
3082
3083 builder
3085 .add_attribute(&RawAttribute::new(
3086 0x8029.into(),
3087 &[0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36],
3088 ))
3089 .unwrap();
3090
3091 assert!(msg.has_attribute(Username::TYPE));
3093 let raw = msg.raw_attribute(Username::TYPE).unwrap();
3094 assert!(Username::try_from(&raw).is_ok());
3095 let username = Username::try_from(&raw).unwrap();
3096 assert_eq!(username.username(), "evtj:h6vY");
3097 builder.add_attribute(&username).unwrap();
3098
3099 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3101 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3102 });
3103 assert!(matches!(
3104 msg.validate_integrity(&credentials),
3105 Ok(IntegrityAlgorithm::Sha1)
3106 ));
3107 builder
3108 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3109 .unwrap();
3110
3111 assert!(msg.has_attribute(Fingerprint::TYPE));
3113 builder.add_fingerprint().unwrap();
3114
3115 let mut msg_data = builder.finish();
3117 msg_data[73] = 0x20;
3119 msg_data[74] = 0x20;
3120 msg_data[75] = 0x20;
3121 assert_eq!(msg_data[..80], data[..80]);
3124 }
3125
3126 #[test]
3127 fn rfc5769_vector2() {
3128 let _log = crate::tests::test_init_log();
3129 let data = vec![
3131 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, ];
3152
3153 let msg = Message::from_bytes(&data).unwrap();
3154 assert!(msg.has_class(MessageClass::Success));
3155 assert!(msg.has_method(BINDING));
3156 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3157 let mut builder = Message::builder(
3158 MessageType::from_class_method(MessageClass::Success, BINDING),
3159 msg.transaction_id(),
3160 MessageWriteVec::new(),
3161 );
3162
3163 assert!(msg.has_attribute(Software::TYPE));
3165 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3166 assert!(Software::try_from(&raw).is_ok());
3167 let software = Software::try_from(&raw).unwrap();
3168 assert_eq!(software.software(), "test vector");
3169 builder.add_attribute(&software).unwrap();
3170
3171 assert!(msg.has_attribute(XorMappedAddress::TYPE));
3173 let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3174 assert!(XorMappedAddress::try_from(&raw).is_ok());
3175 let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3176 assert_eq!(
3177 xor_mapped_addres.addr(msg.transaction_id()),
3178 "192.0.2.1:32853".parse().unwrap()
3179 );
3180 builder.add_attribute(&xor_mapped_addres).unwrap();
3181
3182 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3184 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3185 });
3186 let ret = msg.validate_integrity(&credentials);
3187 warn!("{:?}", ret);
3188 assert!(matches!(ret, Ok(IntegrityAlgorithm::Sha1)));
3189 builder
3190 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3191 .unwrap();
3192
3193 assert!(msg.has_attribute(Fingerprint::TYPE));
3195 builder.add_fingerprint().unwrap();
3196
3197 let mut msg_data = builder.finish();
3199 msg_data[35] = 0x20;
3201 assert_eq!(msg_data[..52], data[..52]);
3202 }
3203
3204 #[test]
3205 fn rfc5769_vector3() {
3206 let _log = crate::tests::test_init_log();
3207 let data = vec![
3209 0x01, 0x01, 0x00, 0x48, 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, 0x14, 0x00, 0x02, 0xa1, 0x47, 0x01, 0x13, 0xa9, 0xfa, 0xa5, 0xd3, 0xf1, 0x79, 0xbc, 0x25, 0xf4, 0xb5, 0xbe, 0xd2, 0xb9, 0xd9, 0x00, 0x08, 0x00, 0x14, 0xa3, 0x82, 0x95, 0x4e, 0x4b, 0xe6, 0x7b, 0xf1, 0x17, 0x84, 0xc9, 0x7c, 0x82, 0x92, 0xc2, 0x75, 0xbf, 0xe3, 0xed, 0x41, 0x80, 0x28, 0x00, 0x04, 0xc8, 0xfb, 0x0b, 0x4c, ];
3233
3234 let msg = Message::from_bytes(&data).unwrap();
3235 assert!(msg.has_class(MessageClass::Success));
3236 assert!(msg.has_method(BINDING));
3237 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3238 let mut builder = Message::builder(
3239 MessageType::from_class_method(MessageClass::Success, BINDING),
3240 msg.transaction_id(),
3241 MessageWriteVec::new(),
3242 );
3243
3244 assert!(msg.has_attribute(Software::TYPE));
3246 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3247 assert!(Software::try_from(&raw).is_ok());
3248 let software = Software::try_from(&raw).unwrap();
3249 assert_eq!(software.software(), "test vector");
3250 builder.add_attribute(&software).unwrap();
3251
3252 assert!(msg.has_attribute(XorMappedAddress::TYPE));
3254 let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3255 assert!(XorMappedAddress::try_from(&raw).is_ok());
3256 let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3257 assert_eq!(
3258 xor_mapped_addres.addr(msg.transaction_id()),
3259 "[2001:db8:1234:5678:11:2233:4455:6677]:32853"
3260 .parse()
3261 .unwrap()
3262 );
3263 builder.add_attribute(&xor_mapped_addres).unwrap();
3264
3265 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3267 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3268 });
3269 assert!(matches!(
3270 msg.validate_integrity(&credentials),
3271 Ok(IntegrityAlgorithm::Sha1)
3272 ));
3273 builder
3274 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3275 .unwrap();
3276
3277 assert!(msg.has_attribute(Fingerprint::TYPE));
3279 builder.add_fingerprint().unwrap();
3280
3281 let mut msg_data = builder.finish();
3283 msg_data[35] = 0x20;
3285 assert_eq!(msg_data[..64], data[..64]);
3286 }
3287
3288 #[test]
3289 fn rfc5769_vector4() {
3290 let _log = crate::tests::test_init_log();
3291 let data = vec![
3293 0x00, 0x01, 0x00, 0x60, 0x21, 0x12, 0xa4, 0x42, 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e, 0x00, 0x06, 0x00, 0x12, 0xe3, 0x83, 0x9e, 0xe3, 0x83, 0x88, 0xe3, 0x83, 0xaa, 0xe3, 0x83, 0x83, 0xe3, 0x82, 0xaf, 0xe3, 0x82, 0xb9, 0x00, 0x00, 0x00, 0x15, 0x00, 0x1c, 0x66, 0x2f, 0x2f, 0x34, 0x39, 0x39, 0x6b, 0x39, 0x35, 0x34, 0x64, 0x36, 0x4f, 0x4c, 0x33, 0x34, 0x6f, 0x4c, 0x39, 0x46, 0x53, 0x54, 0x76, 0x79, 0x36, 0x34, 0x73, 0x41, 0x00, 0x14, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x08, 0x00, 0x14, 0xf6, 0x70, 0x24, 0x65, 0x6d, 0xd6, 0x4a, 0x3e, 0x02, 0xb8, 0xe0, 0x71, 0x2e, 0x85, 0xc9, 0xa2, 0x8c, 0xa8, 0x96, 0x66, ];
3323
3324 let msg = Message::from_bytes(&data).unwrap();
3325 assert!(msg.has_class(MessageClass::Request));
3326 assert!(msg.has_method(BINDING));
3327 assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3328 let mut builder = Message::builder(
3329 MessageType::from_class_method(MessageClass::Request, BINDING),
3330 msg.transaction_id(),
3331 MessageWriteVec::new(),
3332 );
3333
3334 let long_term = LongTermCredentials {
3335 username: "\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}".to_owned(),
3336 password: "The\u{00AD}M\u{00AA}tr\u{2168}".to_owned(),
3337 realm: "example.org".to_owned(),
3338 };
3339 assert!(msg.has_attribute(Username::TYPE));
3341 let raw = msg.raw_attribute(Username::TYPE).unwrap();
3342 assert!(Username::try_from(&raw).is_ok());
3343 let username = Username::try_from(&raw).unwrap();
3344 assert_eq!(username.username(), &long_term.username);
3345 builder.add_attribute(&username).unwrap();
3346
3347 let expected_nonce = "f//499k954d6OL34oL9FSTvy64sA";
3349 assert!(msg.has_attribute(Nonce::TYPE));
3350 let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3351 assert!(Nonce::try_from(&raw).is_ok());
3352 let nonce = Nonce::try_from(&raw).unwrap();
3353 assert_eq!(nonce.nonce(), expected_nonce);
3354 builder.add_attribute(&nonce).unwrap();
3355
3356 assert!(msg.has_attribute(Realm::TYPE));
3358 let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3359 assert!(Realm::try_from(&raw).is_ok());
3360 let realm = Realm::try_from(&raw).unwrap();
3361 assert_eq!(realm.realm(), long_term.realm());
3362 builder.add_attribute(&realm).unwrap();
3363
3364 assert_eq!(builder.finish()[4..], data[4..92]);
3372 }
3373
3374 #[test]
3375 fn rfc8489_vector1() {
3376 let _log = crate::tests::test_init_log();
3377 let data = vec![
3380 0x00, 0x01, 0x00, 0x90, 0x21, 0x12, 0xa4, 0x42, 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e, 0x00, 0x1e, 0x00, 0x20, 0x4a, 0x3c, 0xf3, 0x8f, 0xef, 0x69, 0x92, 0xbd, 0xa9, 0x52, 0xc6, 0x78, 0x04, 0x17, 0xda, 0x0f, 0x24, 0x81, 0x94, 0x15, 0x56, 0x9e, 0x60, 0xb2, 0x05, 0xc4, 0x6e, 0x41, 0x40, 0x7f, 0x17, 0x04, 0x00, 0x15, 0x00, 0x29, 0x6f, 0x62, 0x4d, 0x61, 0x74, 0x4a, 0x6f, 0x73, 0x32, 0x41, 0x41, 0x41, 0x43, 0x66, 0x2f, 0x2f, 0x34, 0x39, 0x39, 0x6b, 0x39, 0x35, 0x34, 0x64, 0x36, 0x4f, 0x4c, 0x33, 0x34, 0x6f, 0x4c, 0x39, 0x46, 0x53, 0x54, 0x76, 0x79, 0x36, 0x34, 0x73, 0x41, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x1d, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x20, 0xb5, 0xc7, 0xbf, 0x00, 0x5b, 0x6c, 0x52, 0xa2, 0x1c, 0x51, 0xc5, 0xe8, 0x92, 0xf8, 0x19, 0x24, 0x13, 0x62, 0x96, 0xcb, 0x92, 0x7c, 0x43, 0x14, 0x93, 0x09, 0x27, 0x8c, 0xc6, 0x51, 0x8e, 0x65, ];
3422
3423 let msg = Message::from_bytes(&data).unwrap();
3424 assert!(msg.has_class(MessageClass::Request));
3425 assert!(msg.has_method(BINDING));
3426 assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3427 let mut builder = Message::builder(
3428 MessageType::from_class_method(MessageClass::Success, BINDING),
3429 msg.transaction_id(),
3430 MessageWriteVec::new(),
3431 );
3432
3433 let long_term = LongTermCredentials {
3434 username: "\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}".to_owned(),
3435 password: "The\u{00AD}M\u{00AA}tr\u{2168}".to_owned(),
3436 realm: "example.org".to_owned(),
3437 };
3438 assert!(msg.has_attribute(Userhash::TYPE));
3440 let raw = msg.raw_attribute(Userhash::TYPE).unwrap();
3441 assert!(Userhash::try_from(&raw).is_ok());
3442 let userhash = Userhash::try_from(&raw).unwrap();
3443 builder.add_attribute(&userhash).unwrap();
3444
3445 let expected_nonce = "obMatJos2AAACf//499k954d6OL34oL9FSTvy64sA";
3447 assert!(msg.has_attribute(Nonce::TYPE));
3448 let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3449 assert!(Nonce::try_from(&raw).is_ok());
3450 let nonce = Nonce::try_from(&raw).unwrap();
3451 assert_eq!(nonce.nonce(), expected_nonce);
3452 builder.add_attribute(&nonce).unwrap();
3453
3454 assert!(msg.has_attribute(Realm::TYPE));
3456 let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3457 assert!(Realm::try_from(&raw).is_ok());
3458 let realm = Realm::try_from(&raw).unwrap();
3459 assert_eq!(realm.realm(), long_term.realm);
3460 builder.add_attribute(&realm).unwrap();
3461
3462 assert!(msg.has_attribute(PasswordAlgorithm::TYPE));
3464 let raw = msg.raw_attribute(PasswordAlgorithm::TYPE).unwrap();
3465 assert!(PasswordAlgorithm::try_from(&raw).is_ok());
3466 let algo = PasswordAlgorithm::try_from(&raw).unwrap();
3467 assert_eq!(algo.algorithm(), PasswordAlgorithmValue::SHA256);
3468 builder.add_attribute(&algo).unwrap();
3469
3470 assert_eq!(builder.finish()[4..], data[4..128]);
3478 }
3479}