1#[cfg(feature = "std")]
88use alloc::collections::BTreeMap;
89use alloc::string::String;
90use alloc::sync::Arc;
91use alloc::vec;
92use alloc::vec::Vec;
93use core::convert::TryFrom;
94#[cfg(feature = "std")]
95use std::sync::{Mutex, OnceLock};
96
97use byteorder::{BigEndian, ByteOrder};
98
99use crate::attribute::*;
100
101use tracing::{error, trace, warn};
102
103use hmac::digest::core_api::CoreWrapper;
104use hmac::digest::CtOutput;
105use hmac::HmacCore;
106
107pub const MAGIC_COOKIE: u32 = 0x2112A442;
109
110#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
112pub struct Method(u16);
113
114impl core::fmt::Display for Method {
115 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
116 write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
117 }
118}
119
120#[cfg(feature = "std")]
121static METHOD_NAME_MAP: OnceLock<Mutex<BTreeMap<Method, &'static str>>> = OnceLock::new();
122
123impl Method {
124 #[cfg(feature = "std")]
126 pub fn add_name(self, name: &'static str) {
127 let mut mnames = METHOD_NAME_MAP
128 .get_or_init(Default::default)
129 .lock()
130 .unwrap();
131 mnames.insert(self, name);
132 }
133
134 pub const fn new(val: u16) -> Self {
146 if val >= 0xf000 {
147 panic!("Method value is out of range!");
148 }
149 Self(val)
150 }
151
152 pub fn value(&self) -> u16 {
162 self.0
163 }
164
165 pub fn name(self) -> &'static str {
173 match self {
174 BINDING => "BINDING",
175 _ => {
176 #[cfg(feature = "std")]
177 {
178 let mnames = METHOD_NAME_MAP
179 .get_or_init(Default::default)
180 .lock()
181 .unwrap();
182 if let Some(name) = mnames.get(&self) {
183 return name;
184 }
185 }
186 "unknown"
187 }
188 }
189 }
190}
191
192pub const BINDING: Method = Method::new(0x0001);
195
196#[derive(Debug, thiserror::Error)]
198#[non_exhaustive]
199pub enum StunParseError {
200 #[error("The provided data is not a STUN message")]
202 NotStun,
203 #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
205 Truncated {
206 expected: usize,
208 actual: usize,
210 },
211 #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
213 TooLarge {
214 expected: usize,
216 actual: usize,
218 },
219 #[error("Integrity value does not match")]
221 IntegrityCheckFailed,
222 #[error("Missing attribute {}", .0)]
224 MissingAttribute(AttributeType),
225 #[error("An attribute {} was encountered after a message integrity attribute", .0)]
227 AttributeAfterIntegrity(AttributeType),
228 #[error("An attribute {} was encountered after a fingerprint attribute", .0)]
230 AttributeAfterFingerprint(AttributeType),
231 #[error("Fingerprint does not match")]
233 FingerprintMismatch,
234 #[error("The provided data does not match the message")]
236 DataMismatch,
237 #[error("The attribute contains invalid data")]
239 InvalidAttributeData,
240 #[error("Cannot parse with this attribute")]
242 WrongAttributeImplementation,
243}
244
245#[derive(Debug, thiserror::Error)]
247#[non_exhaustive]
248pub enum StunWriteError {
249 #[error("The attribute already exists in the message")]
251 AttributeExists(AttributeType),
252 #[error("The message already contains a fingerprint attribute")]
254 FingerprintExists,
255 #[error("The message already contains a message intregrity attribute")]
257 MessageIntegrityExists,
258 #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
260 TooLarge {
261 expected: usize,
263 actual: usize,
265 },
266 #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
268 TooSmall {
269 expected: usize,
271 actual: usize,
273 },
274 #[error("Failed to compute integrity")]
276 IntegrityFailed,
277 #[error("Out of range input provided")]
279 OutOfRange {
280 value: usize,
282 min: usize,
284 max: usize,
286 },
287}
288
289#[derive(Debug, Clone, PartialEq, Eq)]
291#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
292pub struct LongTermCredentials {
293 username: String,
294 password: String,
295 realm: String,
296}
297
298impl LongTermCredentials {
299 pub fn new(username: String, password: String, realm: String) -> Self {
315 Self {
316 username,
317 password,
318 realm,
319 }
320 }
321
322 pub fn username(&self) -> &str {
324 &self.username
325 }
326
327 pub fn password(&self) -> &str {
329 &self.password
330 }
331
332 pub fn realm(&self) -> &str {
334 &self.realm
335 }
336}
337
338#[derive(Debug, Clone, PartialEq, Eq)]
340#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
341pub struct ShortTermCredentials {
342 password: String,
343}
344
345impl ShortTermCredentials {
346 pub fn new(password: String) -> Self {
356 Self { password }
357 }
358
359 pub fn password(&self) -> &str {
361 &self.password
362 }
363}
364
365#[derive(Debug, Clone, PartialEq, Eq)]
369#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
370pub enum MessageIntegrityCredentials {
371 ShortTerm(ShortTermCredentials),
373 LongTerm(LongTermCredentials),
375}
376
377impl From<LongTermCredentials> for MessageIntegrityCredentials {
378 fn from(value: LongTermCredentials) -> Self {
379 MessageIntegrityCredentials::LongTerm(value)
380 }
381}
382
383impl From<ShortTermCredentials> for MessageIntegrityCredentials {
384 fn from(value: ShortTermCredentials) -> Self {
385 MessageIntegrityCredentials::ShortTerm(value)
386 }
387}
388
389impl MessageIntegrityCredentials {
390 pub fn make_key(&self) -> IntegrityKey {
392 match self {
393 MessageIntegrityCredentials::ShortTerm(short) => {
394 IntegrityKey::new(short.password.as_bytes().to_vec())
395 }
396 MessageIntegrityCredentials::LongTerm(long) => {
397 use md5::{Digest, Md5};
398 let mut digest = Md5::new();
399 digest.update(long.username.as_bytes());
400 digest.update(":".as_bytes());
401 digest.update(long.realm.as_bytes());
402 digest.update(":".as_bytes());
403 digest.update(long.password.as_bytes());
404 IntegrityKey::new(digest.finalize().to_vec())
405 }
406 }
407 }
408}
409
410type HmacSha1 = hmac::Hmac<sha1::Sha1>;
411type HmacSha256 = hmac::Hmac<sha2::Sha256>;
412
413#[derive(Debug, Clone)]
415pub struct IntegrityKey {
416 bytes: Vec<u8>,
417 #[cfg(feature = "std")]
418 sha1: Arc<Mutex<Option<HmacSha1>>>,
419 #[cfg(feature = "std")]
420 sha256: Arc<Mutex<Option<HmacSha256>>>,
421}
422
423impl PartialEq<IntegrityKey> for IntegrityKey {
424 fn eq(&self, other: &Self) -> bool {
425 self.bytes == other.bytes
426 }
427}
428
429impl Eq for IntegrityKey {}
430
431impl IntegrityKey {
432 fn new(bytes: Vec<u8>) -> Self {
433 Self {
434 bytes,
435 #[cfg(feature = "std")]
436 sha1: Default::default(),
437 #[cfg(feature = "std")]
438 sha256: Default::default(),
439 }
440 }
441 pub(crate) fn as_bytes(&self) -> &[u8] {
442 &self.bytes
443 }
444
445 pub(crate) fn verify_sha1(&self, data: &[&[u8]], expected: &[u8]) -> bool {
446 use hmac::digest::Output;
447 let computed = self.compute_sha1(data);
448 #[allow(deprecated)]
450 {
451 computed == Output::<sha1::Sha1Core>::from_slice(expected).into()
452 }
453 }
454
455 pub(crate) fn compute_sha1(
456 &self,
457 data: &[&[u8]],
458 ) -> CtOutput<CoreWrapper<HmacCore<CoreWrapper<sha1::Sha1Core>>>> {
459 use hmac::Mac;
460 #[cfg(feature = "std")]
461 let mut sha1 = self.sha1.lock().unwrap();
462 #[cfg(feature = "std")]
463 let hmac = sha1.get_or_insert_with(|| HmacSha1::new_from_slice(self.as_bytes()).unwrap());
464 #[cfg(not(feature = "std"))]
465 let mut hmac = HmacSha1::new_from_slice(self.as_bytes()).unwrap();
466
467 for data in data {
468 hmac.update(data);
469 }
470 #[cfg(feature = "std")]
471 let ret = hmac.finalize_reset();
472 #[cfg(not(feature = "std"))]
473 let ret = hmac.finalize();
474 ret
475 }
476
477 pub(crate) fn verify_sha256(&self, data: &[&[u8]], expected: &[u8]) -> bool {
478 if expected.is_empty() {
479 return false;
480 }
481 let computed = self.compute_sha256(data);
482 if computed.len() < expected.len() {
483 return false;
484 }
485 &computed[..expected.len()] == expected
487 }
488
489 pub(crate) fn compute_sha256(&self, data: &[&[u8]]) -> [u8; 32] {
490 use hmac::Mac;
491 #[cfg(feature = "std")]
492 let mut sha256 = self.sha256.lock().unwrap();
493 #[cfg(feature = "std")]
494 let hmac =
495 sha256.get_or_insert_with(|| HmacSha256::new_from_slice(self.as_bytes()).unwrap());
496 #[cfg(not(feature = "std"))]
497 let mut hmac = HmacSha256::new_from_slice(self.as_bytes()).unwrap();
498
499 for data in data {
500 hmac.update(data);
501 }
502 #[cfg(feature = "std")]
503 let ret = hmac.finalize_reset();
504 #[cfg(not(feature = "std"))]
505 let ret = hmac.finalize();
506 ret.into_bytes().into()
507 }
508}
509
510#[derive(Copy, Clone, Debug, PartialEq, Eq)]
522pub enum MessageClass {
523 Request,
525 Indication,
527 Success,
529 Error,
531}
532
533impl MessageClass {
534 pub fn is_response(self) -> bool {
537 matches!(self, MessageClass::Success | MessageClass::Error)
538 }
539
540 fn to_bits(self) -> u16 {
541 match self {
542 MessageClass::Request => 0x000,
543 MessageClass::Indication => 0x010,
544 MessageClass::Success => 0x100,
545 MessageClass::Error => 0x110,
546 }
547 }
548}
549
550#[derive(Copy, Clone, Debug, PartialEq, Eq)]
552pub struct MessageType(u16);
553
554impl core::fmt::Display for MessageType {
555 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
556 write!(
557 f,
558 "MessageType(class: {:?}, method: {}",
559 self.class(),
560 self.method(),
561 )
562 }
563}
564
565impl MessageType {
566 pub fn from_class_method(class: MessageClass, method: Method) -> Self {
577 let class_bits = MessageClass::to_bits(class);
578 let method = method.value();
579 let method_bits = method & 0xf | (method & 0x70) << 1 | (method & 0xf80) << 2;
580 Self(class_bits | method_bits)
583 }
584
585 pub fn class(self) -> MessageClass {
595 let class = (self.0 & 0x10) >> 4 | (self.0 & 0x100) >> 7;
596 match class {
597 0x0 => MessageClass::Request,
598 0x1 => MessageClass::Indication,
599 0x2 => MessageClass::Success,
600 0x3 => MessageClass::Error,
601 _ => unreachable!(),
602 }
603 }
604
605 pub fn has_class(self, cls: MessageClass) -> bool {
615 self.class() == cls
616 }
617
618 pub fn is_response(self) -> bool {
634 self.class().is_response()
635 }
636
637 pub fn method(self) -> Method {
647 Method::new(self.0 & 0xf | (self.0 & 0xe0) >> 1 | (self.0 & 0x3e00) >> 2)
648 }
649
650 pub fn has_method(self, method: Method) -> bool {
660 self.method() == method
661 }
662
663 pub fn write_into(&self, dest: &mut [u8]) {
665 BigEndian::write_u16(dest, self.0);
666 }
667
668 pub fn to_bytes(self) -> Vec<u8> {
670 let mut ret = vec![0; 2];
671 BigEndian::write_u16(&mut ret[0..2], self.0);
672 ret
673 }
674
675 pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
677 let data = BigEndian::read_u16(data);
678 if data & 0xc000 != 0x0 {
679 return Err(StunParseError::NotStun);
681 }
682 Ok(Self(data))
683 }
684}
685impl TryFrom<&[u8]> for MessageType {
686 type Error = StunParseError;
687
688 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
689 MessageType::from_bytes(value)
690 }
691}
692
693#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
695pub struct TransactionId {
696 id: u128,
697}
698
699impl TransactionId {
700 pub fn generate() -> TransactionId {
702 #[cfg(not(feature = "std"))]
703 {
704 use rand::TryRngCore;
705 let mut dest = [0; 16];
706 rand::rngs::OsRng
707 .try_fill_bytes(&mut dest)
708 .expect("Cannot generate random data");
709 u128::from_be_bytes(dest).into()
710 }
711 #[cfg(feature = "std")]
712 {
713 use rand::Rng;
714 let mut rng = rand::rng();
715 rng.random::<u128>().into()
716 }
717 }
718}
719
720impl From<u128> for TransactionId {
721 fn from(id: u128) -> Self {
722 Self {
723 id: id & 0xffff_ffff_ffff_ffff_ffff_ffff,
724 }
725 }
726}
727impl From<TransactionId> for u128 {
728 fn from(id: TransactionId) -> Self {
729 id.id
730 }
731}
732impl core::fmt::Display for TransactionId {
733 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
734 write!(f, "{:#x}", self.id)
735 }
736}
737
738#[derive(Debug)]
742pub struct MessageHeader {
743 mtype: MessageType,
744 transaction_id: TransactionId,
745 length: u16,
746}
747
748impl MessageHeader {
749 pub const LENGTH: usize = 20;
751
752 pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
765 if data.len() < 20 {
766 return Err(StunParseError::Truncated {
767 expected: 20,
768 actual: data.len(),
769 });
770 }
771 let mtype = MessageType::from_bytes(data)?;
772 let mlength = BigEndian::read_u16(&data[2..]);
773 let tid = BigEndian::read_u128(&data[4..]);
774 let cookie = (tid >> 96) as u32;
775 if cookie != MAGIC_COOKIE {
776 warn!(
777 "malformed cookie constant {:?} != stored data {:?}",
778 MAGIC_COOKIE, cookie
779 );
780 return Err(StunParseError::NotStun);
781 }
782
783 Ok(Self {
784 mtype,
785 transaction_id: tid.into(),
786 length: mlength,
787 })
788 }
789
790 pub fn data_length(&self) -> u16 {
793 self.length
794 }
795
796 pub fn transaction_id(&self) -> TransactionId {
798 self.transaction_id
799 }
800
801 pub fn get_type(&self) -> MessageType {
803 self.mtype
804 }
805
806 fn new(mtype: MessageType, transaction_id: TransactionId, length: u16) -> Self {
807 Self {
808 mtype,
809 transaction_id,
810 length,
811 }
812 }
813
814 fn write_into(&self, dest: &mut [u8]) {
815 self.mtype.write_into(&mut dest[..2]);
816 let transaction: u128 = self.transaction_id.into();
817 let tid = (MAGIC_COOKIE as u128) << 96 | transaction & 0xffff_ffff_ffff_ffff_ffff_ffff;
818 BigEndian::write_u128(&mut dest[4..20], tid);
819 BigEndian::write_u16(&mut dest[2..4], self.length);
820 }
821}
822
823#[derive(Debug, Clone, Copy)]
828pub struct Message<'a> {
829 data: &'a [u8],
830}
831
832impl core::fmt::Display for Message<'_> {
833 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
834 write!(
835 f,
836 "Message(class: {:?}, method: {}, transaction: {}, attributes: ",
837 self.get_type().class(),
838 self.get_type().method(),
839 self.transaction_id()
840 )?;
841 let iter = self.iter_attributes();
842 write!(f, "[")?;
843 for (i, (_offset, a)) in iter.enumerate() {
844 if i > 0 {
845 write!(f, ", ")?;
846 }
847 write!(f, "{a}")?;
848 }
849 write!(f, "]")?;
850 write!(f, ")")
851 }
852}
853
854#[derive(Clone, Copy, Debug, PartialEq, Eq)]
856pub enum IntegrityAlgorithm {
857 Sha1,
859 Sha256,
861}
862
863impl<'a> Message<'a> {
864 pub fn builder<B: MessageWrite>(
880 mtype: MessageType,
881 transaction_id: TransactionId,
882 mut write: B,
883 ) -> B {
884 let mut data = [0; 20];
885 MessageHeader::new(mtype, transaction_id, 0).write_into(&mut data);
886 write.push_data(&data);
887 write
888 }
889
890 pub fn builder_request<B: MessageWrite>(method: Method, write: B) -> B {
904 Message::builder(
905 MessageType::from_class_method(MessageClass::Request, method),
906 TransactionId::generate(),
907 write,
908 )
909 }
910
911 pub fn builder_success<B: MessageWrite>(orig: &Message, write: B) -> B {
931 if !orig.has_class(MessageClass::Request) {
932 panic!(
933 "A success response message was attempted to be created from a non-request message"
934 );
935 }
936 Message::builder(
937 MessageType::from_class_method(MessageClass::Success, orig.method()),
938 orig.transaction_id(),
939 write,
940 )
941 }
942
943 pub fn builder_error<B: MessageWrite>(orig: &Message, write: B) -> B {
963 if !orig.has_class(MessageClass::Request) {
964 panic!(
965 "An error response message was attempted to be created from a non-request message"
966 );
967 }
968 Message::builder(
969 MessageType::from_class_method(MessageClass::Error, orig.method()),
970 orig.transaction_id(),
971 write,
972 )
973 }
974
975 pub fn builder_indication<B: MessageWrite>(method: Method, write: B) -> B {
989 Message::builder(
990 MessageType::from_class_method(MessageClass::Indication, method),
991 TransactionId::generate(),
992 write,
993 )
994 }
995
996 pub fn get_type(&self) -> MessageType {
1010 MessageType::try_from(&self.data[..2]).unwrap()
1011 }
1012
1013 pub fn class(&self) -> MessageClass {
1025 self.get_type().class()
1026 }
1027
1028 pub fn has_class(&self, cls: MessageClass) -> bool {
1040 self.class() == cls
1041 }
1042
1043 pub fn is_response(&self) -> bool {
1065 self.class().is_response()
1066 }
1067
1068 pub fn method(&self) -> Method {
1080 self.get_type().method()
1081 }
1082
1083 pub fn has_method(&self, method: Method) -> bool {
1096 self.method() == method
1097 }
1098
1099 pub fn transaction_id(&self) -> TransactionId {
1113 BigEndian::read_u128(&self.data[4..]).into()
1114 }
1115
1116 #[tracing::instrument(
1138 name = "message_from_bytes",
1139 level = "trace",
1140 skip(data),
1141 fields(
1142 data.len = data.len()
1143 )
1144 )]
1145 pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
1146 let orig_data = data;
1147
1148 let header = MessageHeader::from_bytes(data)?;
1149 let mlength = header.data_length() as usize;
1150 if mlength + MessageHeader::LENGTH > data.len() {
1151 warn!(
1153 "malformed advertised size {} and data size {} don't match",
1154 mlength + 20,
1155 data.len()
1156 );
1157 return Err(StunParseError::Truncated {
1158 expected: mlength + MessageHeader::LENGTH,
1159 actual: data.len(),
1160 });
1161 }
1162
1163 let ending_attributes = [
1164 MessageIntegrity::TYPE,
1165 MessageIntegritySha256::TYPE,
1166 Fingerprint::TYPE,
1167 ];
1168 let mut seen_ending_attributes = [AttributeType::new(0); 3];
1170 let mut seen_ending_len = 0;
1171 let mut data_offset = MessageHeader::LENGTH;
1172 for attr in MessageRawAttributesIter::new(data) {
1173 let (_offset, attr) = attr.map_err(|e| {
1174 warn!("failed to parse message attribute at offset {data_offset}: {e}",);
1175 e
1176 })?;
1177
1178 if seen_ending_len > 0 && !ending_attributes.contains(&attr.get_type()) {
1181 if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1182 warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1183 return Ok(Message { data: orig_data });
1184 } else {
1185 warn!(
1187 "unexpected attribute {} after MESSAGE_INTEGRITY",
1188 attr.get_type()
1189 );
1190 return Ok(Message { data: orig_data });
1191 }
1192 }
1193
1194 if ending_attributes.contains(&attr.get_type()) {
1195 if seen_ending_attributes.contains(&attr.get_type()) {
1196 if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1197 warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1198 return Ok(Message { data: orig_data });
1199 } else {
1200 warn!(
1202 "unexpected attribute {} after MESSAGE_INTEGRITY",
1203 attr.get_type()
1204 );
1205 return Ok(Message { data: orig_data });
1206 }
1207 } else {
1208 seen_ending_attributes[seen_ending_len] = attr.get_type();
1209 seen_ending_len += 1;
1210 }
1212 }
1213 let padded_len = attr.padded_len();
1214 if attr.get_type() == Fingerprint::TYPE {
1215 let f = Fingerprint::from_raw_ref(&attr)?;
1216 let msg_fingerprint = f.fingerprint();
1217 let mut header = [0; 4];
1218 header[0] = orig_data[0];
1219 header[1] = orig_data[1];
1220 BigEndian::write_u16(
1221 &mut header[2..4],
1222 (data_offset + padded_len - MessageHeader::LENGTH) as u16,
1223 );
1224 let fingerprint_data = &orig_data[4..data_offset];
1225 let calculated_fingerprint = Fingerprint::compute(&[&header, fingerprint_data]);
1226 if &calculated_fingerprint != msg_fingerprint {
1227 warn!(
1228 "fingerprint mismatch {:?} != {:?}",
1229 calculated_fingerprint, msg_fingerprint
1230 );
1231 return Err(StunParseError::FingerprintMismatch);
1232 }
1233 }
1234 data_offset += padded_len;
1235 }
1236 Ok(Message { data: orig_data })
1237 }
1238
1239 pub fn validate_integrity(
1262 &self,
1263 credentials: &MessageIntegrityCredentials,
1264 ) -> Result<IntegrityAlgorithm, StunParseError> {
1265 let key = credentials.make_key();
1266 self.validate_integrity_with_key(&key)
1267 }
1268
1269 #[tracing::instrument(
1271 name = "message_validate_integrity_with_key",
1272 level = "trace",
1273 skip(self, key),
1274 fields(
1275 msg.transaction = %self.transaction_id(),
1276 )
1277 )]
1278 pub fn validate_integrity_with_key(
1279 &self,
1280 key: &IntegrityKey,
1281 ) -> Result<IntegrityAlgorithm, StunParseError> {
1282 let raw_sha1 = self.raw_attribute(MessageIntegrity::TYPE);
1283 let raw_sha256 = self.raw_attribute(MessageIntegritySha256::TYPE);
1284 let (algo, msg_hmac) = match (raw_sha1, raw_sha256) {
1285 (_, Some(sha256)) => {
1286 let integrity = MessageIntegritySha256::try_from(&sha256)?;
1287 (IntegrityAlgorithm::Sha256, integrity.hmac().to_vec())
1288 }
1289 (Some(sha1), None) => {
1290 let integrity = MessageIntegrity::try_from(&sha1)?;
1291 (IntegrityAlgorithm::Sha1, integrity.hmac().to_vec())
1292 }
1293 (None, None) => return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE)),
1294 };
1295
1296 let data = self.data;
1299 debug_assert!(data.len() >= MessageHeader::LENGTH);
1300 let mut data = &data[MessageHeader::LENGTH..];
1301 let mut data_offset = MessageHeader::LENGTH;
1302 while !data.is_empty() {
1303 let attr = RawAttribute::from_bytes(data)?;
1304 if algo == IntegrityAlgorithm::Sha1 && attr.get_type() == MessageIntegrity::TYPE {
1305 let msg = MessageIntegrity::try_from(&attr)?;
1306 debug_assert!(msg.hmac().as_slice() == msg_hmac);
1307
1308 let mut header = [0; 4];
1311 header[0] = self.data[0];
1312 header[1] = self.data[1];
1313 let hmac_data = &self.data[4..data_offset];
1314 BigEndian::write_u16(
1315 &mut header[2..4],
1316 data_offset as u16 + 24 - MessageHeader::LENGTH as u16,
1317 );
1318 MessageIntegrity::verify(
1319 &[header.as_slice(), hmac_data],
1320 key,
1321 msg_hmac.as_slice().try_into().unwrap(),
1322 )?;
1323 return Ok(algo);
1324 } else if algo == IntegrityAlgorithm::Sha256
1325 && attr.get_type() == MessageIntegritySha256::TYPE
1326 {
1327 let msg = MessageIntegritySha256::try_from(&attr)?;
1328 debug_assert!(msg.hmac() == msg_hmac);
1329
1330 let mut header = [0; 4];
1333 header[0] = self.data[0];
1334 header[1] = self.data[1];
1335 let hmac_data = &self.data[4..data_offset];
1336 BigEndian::write_u16(
1337 &mut header[2..4],
1338 data_offset as u16 + attr.padded_len() as u16 - MessageHeader::LENGTH as u16,
1339 );
1340 MessageIntegritySha256::verify(&[&header, hmac_data], key, &msg_hmac)?;
1341 return Ok(algo);
1342 }
1343 let padded_len = attr.padded_len();
1344 debug_assert!(padded_len <= data.len());
1346 data = &data[padded_len..];
1347 data_offset += padded_len;
1348 }
1349
1350 unreachable!();
1353 }
1354
1355 pub fn nth_raw_attribute(&self, atype: AttributeType, n: usize) -> Option<RawAttribute<'_>> {
1374 self.nth_raw_attribute_and_offset(atype, n)
1375 .map(|(_offset, attr)| attr)
1376 }
1377
1378 pub fn raw_attribute(&self, atype: AttributeType) -> Option<RawAttribute<'_>> {
1382 self.nth_raw_attribute(atype, 0)
1383 }
1384
1385 #[tracing::instrument(
1407 name = "message_nth_raw_attribute_and_offset",
1408 level = "trace",
1409 skip(self, atype),
1410 fields(
1411 msg.transaction = %self.transaction_id(),
1412 attribute_type = %atype,
1413 )
1414 )]
1415 pub fn nth_raw_attribute_and_offset(
1416 &self,
1417 atype: AttributeType,
1418 n: usize,
1419 ) -> Option<(usize, RawAttribute<'_>)> {
1420 if let Some((offset, attr)) = self
1421 .iter_attributes()
1422 .filter(|(_offset, attr)| attr.get_type() == atype)
1423 .nth(n)
1424 {
1425 trace!("found attribute at offset: {offset}");
1426 Some((offset, attr))
1427 } else {
1428 trace!("could not find attribute");
1429 None
1430 }
1431 }
1432
1433 pub fn raw_attribute_and_offset(
1438 &self,
1439 atype: AttributeType,
1440 ) -> Option<(usize, RawAttribute<'_>)> {
1441 self.nth_raw_attribute_and_offset(atype, 0)
1442 }
1443
1444 pub fn nth_attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1466 &'a self,
1467 n: usize,
1468 ) -> Result<A, StunParseError> {
1469 self.nth_attribute_and_offset(n).map(|(_offset, attr)| attr)
1470 }
1471
1472 pub fn attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1476 &'a self,
1477 ) -> Result<A, StunParseError> {
1478 self.nth_attribute(0)
1479 }
1480
1481 pub fn nth_attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1507 &'a self,
1508 n: usize,
1509 ) -> Result<(usize, A), StunParseError> {
1510 self.nth_raw_attribute_and_offset(A::TYPE, n)
1511 .ok_or(StunParseError::MissingAttribute(A::TYPE))
1512 .and_then(|(offset, raw)| A::from_raw(raw).map(|attr| (offset, attr)))
1513 }
1514
1515 pub fn attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1520 &'a self,
1521 ) -> Result<(usize, A), StunParseError> {
1522 self.nth_attribute_and_offset(0)
1523 }
1524
1525 pub fn iter_attributes(&self) -> impl Iterator<Item = (usize, RawAttribute<'_>)> {
1527 MessageAttributesIter::new(self.data)
1528 }
1529
1530 #[tracing::instrument(
1578 level = "trace",
1579 skip(msg, write),
1580 fields(
1581 msg.transaction = %msg.transaction_id(),
1582 )
1583 )]
1584 pub fn check_attribute_types<B: MessageWrite>(
1585 msg: &Message,
1586 supported: &[AttributeType],
1587 required_in_msg: &[AttributeType],
1588 write: B,
1589 ) -> Option<B> {
1590 let unsupported: Vec<AttributeType> = msg
1592 .iter_attributes()
1593 .map(|(_offset, a)| a.get_type())
1594 .filter(|at| at.comprehension_required() && !supported.contains(at))
1596 .collect();
1597 if !unsupported.is_empty() {
1598 warn!(
1599 "Message contains unknown comprehension required attributes {:?}, returning unknown attributes",
1600 unsupported
1601 );
1602 return Some(Message::unknown_attributes(msg, &unsupported, write));
1603 }
1604 let has_required_attribute_missing = required_in_msg
1605 .iter()
1606 .any(|&at| {
1608 !msg.iter_attributes()
1609 .map(|(_offset, a)| a.get_type())
1610 .any(|a| a == at)
1611 });
1612 if has_required_attribute_missing {
1613 warn!("Message is missing required attributes, returning bad request");
1614 return Some(Message::bad_request(msg, write));
1615 }
1616 None
1617 }
1618
1619 pub fn unknown_attributes<B: MessageWrite>(
1640 src: &Message,
1641 attributes: &[AttributeType],
1642 write: B,
1643 ) -> B {
1644 let mut out = Message::builder_error(src, write);
1645 let software = Software::new("stun-types").unwrap();
1646 out.add_attribute(&software).unwrap();
1647 let error = ErrorCode::new(420, "Unknown Attributes").unwrap();
1648 out.add_attribute(&error).unwrap();
1649 let unknown = UnknownAttributes::new(attributes);
1650 if !attributes.is_empty() {
1651 out.add_attribute(&unknown).unwrap();
1652 }
1653 out
1654 }
1655
1656 pub fn bad_request<B: MessageWrite>(src: &Message, write: B) -> B {
1674 let mut out = Message::builder_error(src, write);
1675 let software = Software::new("stun-types").unwrap();
1676 out.add_attribute(&software).unwrap();
1677 let error = ErrorCode::new(400, "Bad Request").unwrap();
1678 out.add_attribute(&error).unwrap();
1679 out
1680 }
1681
1682 pub fn has_attribute(&self, atype: AttributeType) -> bool {
1698 self.iter_attributes()
1699 .any(|(_offset, attr)| attr.get_type() == atype)
1700 }
1701
1702 pub fn as_bytes(&self) -> &[u8] {
1704 self.data
1705 }
1706}
1707impl<'a> TryFrom<&'a [u8]> for Message<'a> {
1708 type Error = StunParseError;
1709
1710 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
1711 Message::from_bytes(value)
1712 }
1713}
1714
1715impl AsRef<[u8]> for Message<'_> {
1716 fn as_ref(&self) -> &[u8] {
1717 self.data
1718 }
1719}
1720
1721#[derive(Debug)]
1722struct MessageRawAttributesIter<'a> {
1723 data: &'a [u8],
1724 data_i: usize,
1725}
1726
1727impl<'a> MessageRawAttributesIter<'a> {
1728 fn new(data: &'a [u8]) -> Self {
1729 Self {
1730 data,
1731 data_i: MessageHeader::LENGTH,
1732 }
1733 }
1734}
1735
1736impl<'a> Iterator for MessageRawAttributesIter<'a> {
1737 type Item = Result<(usize, RawAttribute<'a>), StunParseError>;
1738
1739 fn next(&mut self) -> Option<Self::Item> {
1740 if self.data_i >= self.data.len() {
1741 return None;
1742 }
1743
1744 match RawAttribute::from_bytes(&self.data[self.data_i..]) {
1745 Ok(attr) => {
1746 let padded_len = attr.padded_len();
1747 self.data_i += padded_len;
1748 if self.data_i > self.data.len() {
1749 warn!(
1750 "attribute {} extends past the end of the data",
1751 attr.get_type()
1752 );
1753 return Some(Err(StunParseError::Truncated {
1754 expected: self.data_i,
1755 actual: self.data.len(),
1756 }));
1757 }
1758 Some(Ok((self.data_i - padded_len, attr)))
1759 }
1760 Err(e) => {
1761 let offset = self.data_i;
1762 self.data_i = self.data.len();
1763 let e = match e {
1764 StunParseError::Truncated { expected, actual } => StunParseError::Truncated {
1765 expected: expected + 4 + offset,
1766 actual: actual + 4 + offset,
1767 },
1768 StunParseError::TooLarge { expected, actual } => StunParseError::TooLarge {
1769 expected: expected + 4 + offset,
1770 actual: actual + 4 + offset,
1771 },
1772 e => e,
1773 };
1774 Some(Err(e))
1775 }
1776 }
1777 }
1778}
1779
1780#[doc(hidden)]
1781#[derive(Debug)]
1782pub struct MessageAttributesIter<'a> {
1783 header_parsed: bool,
1784 inner: MessageRawAttributesIter<'a>,
1785 last_attr_type: AttributeType,
1786 seen_message_integrity: bool,
1787}
1788
1789impl<'a> MessageAttributesIter<'a> {
1790 pub fn new(data: &'a [u8]) -> Self {
1799 Self {
1800 header_parsed: false,
1801 inner: MessageRawAttributesIter::new(data),
1802 seen_message_integrity: false,
1803 last_attr_type: AttributeType::new(0),
1804 }
1805 }
1806}
1807
1808impl<'a> Iterator for MessageAttributesIter<'a> {
1809 type Item = (usize, RawAttribute<'a>);
1810
1811 fn next(&mut self) -> Option<Self::Item> {
1812 if self.last_attr_type == Fingerprint::TYPE {
1814 return None;
1815 }
1816
1817 if !self.header_parsed {
1818 let Ok(hdr) = MessageHeader::from_bytes(self.inner.data) else {
1819 self.last_attr_type = Fingerprint::TYPE;
1820 return None;
1821 };
1822 if hdr.data_length() as usize + MessageHeader::LENGTH > self.inner.data.len() {
1823 self.last_attr_type = Fingerprint::TYPE;
1824 return None;
1825 }
1826 self.header_parsed = true;
1827 }
1828
1829 let (offset, attr) = self.inner.next()?.ok()?;
1830 let attr_type = attr.get_type();
1831 if self.seen_message_integrity {
1832 if self.last_attr_type != Fingerprint::TYPE && attr_type == Fingerprint::TYPE {
1833 self.last_attr_type = attr_type;
1834 return Some((offset, attr));
1835 }
1836 if self.last_attr_type == MessageIntegrity::TYPE
1837 && attr_type == MessageIntegritySha256::TYPE
1838 {
1839 self.last_attr_type = attr_type;
1840 return Some((offset, attr));
1841 }
1842 self.last_attr_type = Fingerprint::TYPE;
1843 return None;
1844 }
1845 if attr.get_type() == MessageIntegrity::TYPE
1846 || attr.get_type() == MessageIntegritySha256::TYPE
1847 || attr.get_type() == Fingerprint::TYPE
1848 {
1849 self.seen_message_integrity = true;
1850 }
1851 self.last_attr_type = attr.get_type();
1852
1853 Some((offset, attr))
1854 }
1855}
1856
1857#[allow(clippy::len_without_is_empty)]
1858pub trait MessageWrite {
1860 type Output;
1862 fn max_size(&self) -> Option<usize> {
1865 None
1866 }
1867
1868 fn mut_data(&mut self) -> &mut [u8];
1870 fn data(&self) -> &[u8];
1872 fn len(&self) -> usize;
1874 fn push_data(&mut self, data: &[u8]);
1876 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite);
1878
1879 fn has_attribute(&self, atype: AttributeType) -> bool;
1881
1882 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType>;
1885
1886 fn finish(self) -> Self::Output;
1888}
1889
1890pub trait MessageWriteExt: MessageWrite {
1892 fn get_type(&self) -> MessageType {
1904 MessageType::from_bytes(self.data()).unwrap()
1905 }
1906
1907 fn class(&self) -> MessageClass {
1919 self.get_type().class()
1920 }
1921
1922 fn has_class(&self, cls: MessageClass) -> bool {
1934 self.class() == cls
1935 }
1936
1937 fn is_response(&self) -> bool {
1959 self.class().is_response()
1960 }
1961
1962 fn method(&self) -> Method {
1974 self.get_type().method()
1975 }
1976
1977 fn has_method(&self, method: Method) -> bool {
1990 self.method() == method
1991 }
1992
1993 fn transaction_id(&self) -> TransactionId {
2007 BigEndian::read_u128(&self.data()[4..]).into()
2008 }
2009
2010 fn add_message_integrity(
2045 &mut self,
2046 credentials: &MessageIntegrityCredentials,
2047 algorithm: IntegrityAlgorithm,
2048 ) -> Result<(), StunWriteError> {
2049 let key = credentials.make_key();
2050 self.add_message_integrity_with_key(&key, algorithm)
2051 }
2052
2053 #[tracing::instrument(
2055 name = "message_add_integrity_with_key",
2056 level = "trace",
2057 err,
2058 skip(self),
2059 fields(
2060 msg.transaction = %self.transaction_id(),
2061 )
2062 )]
2063 fn add_message_integrity_with_key(
2064 &mut self,
2065 key: &IntegrityKey,
2066 algorithm: IntegrityAlgorithm,
2067 ) -> Result<(), StunWriteError> {
2068 let mut atypes = [AttributeType::new(0); 3];
2069 let mut i = 0;
2070 atypes[i] = match algorithm {
2071 IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2072 IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2073 };
2074 i += 1;
2075 if algorithm == IntegrityAlgorithm::Sha1 {
2076 atypes[i] = MessageIntegritySha256::TYPE;
2077 i += 1;
2078 }
2079 atypes[i] = Fingerprint::TYPE;
2080 i += 1;
2081
2082 match self.has_any_attribute(&atypes[..i]) {
2083 Some(MessageIntegrity::TYPE) => {
2085 return Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2086 }
2087 Some(MessageIntegritySha256::TYPE) => {
2088 return Err(StunWriteError::AttributeExists(
2089 MessageIntegritySha256::TYPE,
2090 ));
2091 }
2092 Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2093 _ => (),
2094 }
2095 match algorithm {
2096 IntegrityAlgorithm::Sha1 => {
2097 check_attribute_can_fit(self, &MessageIntegrity::new([0; 20]))?
2098 }
2099 IntegrityAlgorithm::Sha256 => {
2100 check_attribute_can_fit(self, &MessageIntegritySha256::new(&[0; 32]).unwrap())?
2101 }
2102 };
2103
2104 add_message_integrity_unchecked(self, key, algorithm);
2105
2106 Ok(())
2107 }
2108
2109 #[tracing::instrument(
2127 name = "message_add_fingerprint",
2128 level = "trace",
2129 skip(self),
2130 fields(
2131 msg.transaction = %self.transaction_id(),
2132 )
2133 )]
2134 fn add_fingerprint(&mut self) -> Result<(), StunWriteError> {
2135 if self.has_attribute(Fingerprint::TYPE) {
2136 return Err(StunWriteError::AttributeExists(Fingerprint::TYPE));
2137 }
2138
2139 check_attribute_can_fit(self, &Fingerprint::new([0; 4]))?;
2140 add_fingerprint_unchecked(self);
2141
2142 Ok(())
2143 }
2144
2145 #[tracing::instrument(
2176 name = "message_add_attribute",
2177 level = "trace",
2178 err,
2179 skip(self, attr),
2180 fields(
2181 msg.transaction = %self.transaction_id(),
2182 )
2183 )]
2184 fn add_attribute(&mut self, attr: &dyn AttributeWrite) -> Result<(), StunWriteError> {
2185 let ty = attr.get_type();
2186 match ty {
2187 MessageIntegrity::TYPE => {
2188 panic!("Cannot write MessageIntegrity with `add_attribute`. Use add_message_integrity() instead");
2189 }
2190 MessageIntegritySha256::TYPE => {
2191 panic!("Cannot write MessageIntegritySha256 with `add_attribute`. Use add_message_integrity() instead");
2192 }
2193 Fingerprint::TYPE => {
2194 panic!(
2195 "Cannot write Fingerprint with `add_attribute`. Use add_fingerprint() instead"
2196 );
2197 }
2198 _ => (),
2199 }
2200 match self.has_any_attribute(&[
2201 MessageIntegrity::TYPE,
2202 MessageIntegritySha256::TYPE,
2203 Fingerprint::TYPE,
2204 ]) {
2205 Some(MessageIntegrity::TYPE) => return Err(StunWriteError::MessageIntegrityExists),
2207 Some(MessageIntegritySha256::TYPE) => {
2208 return Err(StunWriteError::MessageIntegrityExists)
2209 }
2210 Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2211 _ => (),
2212 }
2213 check_attribute_can_fit(self, attr)?;
2214 self.push_attribute_unchecked(attr);
2215 Ok(())
2216 }
2217}
2218
2219impl<T: MessageWrite> MessageWriteExt for T {}
2220
2221#[derive(Debug, Default)]
2223pub struct MessageWriteVec {
2224 output: Vec<u8>,
2225 attributes: smallvec::SmallVec<[AttributeType; 16]>,
2226}
2227
2228impl MessageWriteVec {
2229 pub fn new() -> Self {
2231 Self::default()
2232 }
2233
2234 pub fn with_capacity(capacity: usize) -> Self {
2236 Self {
2237 output: Vec::with_capacity(capacity),
2238 attributes: Default::default(),
2239 }
2240 }
2241}
2242
2243impl core::ops::Deref for MessageWriteVec {
2244 type Target = Vec<u8>;
2245 fn deref(&self) -> &Self::Target {
2246 &self.output
2247 }
2248}
2249
2250impl core::ops::DerefMut for MessageWriteVec {
2251 fn deref_mut(&mut self) -> &mut Self::Target {
2252 &mut self.output
2253 }
2254}
2255
2256impl MessageWrite for MessageWriteVec {
2257 type Output = Vec<u8>;
2258
2259 fn mut_data(&mut self) -> &mut [u8] {
2260 &mut self.output
2261 }
2262
2263 fn data(&self) -> &[u8] {
2264 &self.output
2265 }
2266
2267 fn len(&self) -> usize {
2268 self.output.len()
2269 }
2270
2271 fn push_data(&mut self, data: &[u8]) {
2272 self.output.extend(data)
2273 }
2274
2275 fn finish(self) -> Self::Output {
2276 self.output
2277 }
2278
2279 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2280 let offset = self.output.len();
2281 let padded_len = attr.padded_len();
2282 let expected = offset + padded_len;
2283 BigEndian::write_u16(
2284 &mut self.output[2..4],
2285 (expected - MessageHeader::LENGTH) as u16,
2286 );
2287 self.output.resize(expected, 0);
2288 attr.write_into_unchecked(&mut self.output[offset..]);
2289 self.attributes.push(attr.get_type());
2290 }
2291
2292 fn has_attribute(&self, atype: AttributeType) -> bool {
2293 self.attributes.contains(&atype)
2294 }
2295
2296 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2297 self.attributes
2298 .iter()
2299 .find(|&typ| atypes.contains(typ))
2300 .cloned()
2301 }
2302}
2303
2304#[derive(Debug, Default)]
2306pub struct MessageWriteMutSlice<'a> {
2307 output: &'a mut [u8],
2308 offset: usize,
2309 attributes: smallvec::SmallVec<[AttributeType; 16]>,
2310}
2311
2312impl<'a> MessageWriteMutSlice<'a> {
2313 pub fn new(data: &'a mut [u8]) -> Self {
2315 Self {
2316 output: data,
2317 offset: 0,
2318 attributes: Default::default(),
2319 }
2320 }
2321}
2322
2323impl core::ops::Deref for MessageWriteMutSlice<'_> {
2324 type Target = [u8];
2325 fn deref(&self) -> &Self::Target {
2326 self.output
2327 }
2328}
2329
2330impl core::ops::DerefMut for MessageWriteMutSlice<'_> {
2331 fn deref_mut(&mut self) -> &mut Self::Target {
2332 self.output
2333 }
2334}
2335
2336impl<'a> MessageWrite for MessageWriteMutSlice<'a> {
2337 type Output = usize;
2338
2339 fn max_size(&self) -> Option<usize> {
2340 Some(self.output.len())
2341 }
2342
2343 fn mut_data(&mut self) -> &mut [u8] {
2344 &mut self.output[..self.offset]
2345 }
2346
2347 fn data(&self) -> &[u8] {
2348 &self.output[..self.offset]
2349 }
2350
2351 fn len(&self) -> usize {
2352 self.offset
2353 }
2354
2355 fn push_data(&mut self, data: &[u8]) {
2356 let len = data.len();
2357 self.output[self.offset..self.offset + len].copy_from_slice(data);
2358 self.offset += len;
2359 }
2360
2361 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2362 let padded_len = attr.padded_len();
2363 let expected = self.offset + padded_len;
2364 BigEndian::write_u16(
2365 &mut self.output[2..4],
2366 (expected - MessageHeader::LENGTH) as u16,
2367 );
2368 self.attributes.push(attr.get_type());
2369 attr.write_into(&mut self.output[self.offset..self.offset + padded_len])
2370 .unwrap();
2371 self.offset += padded_len;
2372 }
2373
2374 fn finish(self) -> Self::Output {
2375 self.offset
2376 }
2377
2378 fn has_attribute(&self, atype: AttributeType) -> bool {
2379 self.attributes.contains(&atype)
2380 }
2381
2382 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2383 self.attributes
2384 .iter()
2385 .find(|&typ| atypes.contains(typ))
2386 .cloned()
2387 }
2388}
2389
2390fn check_attribute_can_fit<O, T: MessageWrite<Output = O> + ?Sized>(
2391 this: &mut T,
2392 attr: &dyn AttributeWrite,
2393) -> Result<usize, StunWriteError> {
2394 let len = attr.padded_len();
2395 let out_data = this.data();
2396 if out_data.len() < MessageHeader::LENGTH {
2397 return Err(StunWriteError::TooSmall {
2398 expected: 20,
2399 actual: out_data.len(),
2400 });
2401 }
2402 let expected = BigEndian::read_u16(&out_data[2..4]) as usize + MessageHeader::LENGTH + len;
2403 if let Some(max) = this.max_size() {
2404 if max < expected {
2405 return Err(StunWriteError::TooSmall {
2406 expected,
2407 actual: max,
2408 });
2409 }
2410 }
2411 Ok(expected)
2412}
2413
2414fn add_message_integrity_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(
2415 this: &mut T,
2416 key: &IntegrityKey,
2417 algorithm: IntegrityAlgorithm,
2418) {
2419 match algorithm {
2422 IntegrityAlgorithm::Sha1 => {
2423 this.push_attribute_unchecked(&MessageIntegrity::new([0; 20]));
2424 let len = this.len();
2425 let data = this.mut_data();
2426 let integrity = MessageIntegrity::compute(&[&data[..len - 24]], key).unwrap();
2427 data[len - 20..].copy_from_slice(&integrity);
2428 }
2429 IntegrityAlgorithm::Sha256 => {
2430 this.push_attribute_unchecked(&MessageIntegritySha256::new(&[0; 32]).unwrap());
2431 let len = this.len();
2432 let data = this.mut_data();
2433 let integrity = MessageIntegritySha256::compute(&[&data[..len - 36]], key).unwrap();
2434 data[len - 32..].copy_from_slice(&integrity);
2435 }
2436 }
2437}
2438
2439fn add_fingerprint_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(this: &mut T) {
2440 this.push_attribute_unchecked(&Fingerprint::new([0; 4]));
2443 let len = this.len();
2444 let data = this.mut_data();
2445 let fingerprint = Fingerprint::compute(&[&data[..len - 8]]);
2446 let fingerprint = Fingerprint::new(fingerprint);
2447 fingerprint.write_into(&mut data[len - 8..]).unwrap();
2448}
2449
2450#[cfg(test)]
2451mod tests {
2452 use alloc::borrow::ToOwned;
2453 use tracing::error;
2454
2455 use super::*;
2456
2457 #[test]
2458 #[should_panic(expected = "Method value is out of range")]
2459 fn method_value_out_of_range() {
2460 let _log = crate::tests::test_init_log();
2461 Method::new(0xf000);
2462 }
2463
2464 #[test]
2465 #[cfg(feature = "std")]
2466 fn method_name() {
2467 let _log = crate::tests::test_init_log();
2468 assert_eq!(BINDING.name(), "BINDING");
2469 let method = Method::new(0x111);
2470 method.add_name("SOME-NAME");
2471 assert_eq!(method.name(), "SOME-NAME");
2472 assert_eq!(Method::new(0x112).name(), "unknown");
2473 }
2474
2475 #[test]
2476 fn msg_type_roundtrip() {
2477 let _log = crate::tests::test_init_log();
2478 for m in 0..0xfff {
2480 let m = Method::new(m);
2481 let classes = vec![
2482 MessageClass::Request,
2483 MessageClass::Indication,
2484 MessageClass::Success,
2485 MessageClass::Error,
2486 ];
2487 for c in classes {
2488 let mtype = MessageType::from_class_method(c, m);
2489 trace!("{mtype}");
2490 assert_eq!(mtype.class(), c);
2491 assert!(mtype.has_class(c));
2492 assert_eq!(mtype.method(), m);
2493 assert!(mtype.has_method(m));
2494 let bytes = mtype.to_bytes();
2495 let ptype = MessageType::from_bytes(&bytes).unwrap();
2496 assert_eq!(mtype, ptype);
2497 }
2498 }
2499 }
2500
2501 #[test]
2502 fn msg_type_not_stun() {
2503 assert!(matches!(
2504 MessageType::from_bytes(&[0xc0, 0x00]),
2505 Err(StunParseError::NotStun)
2506 ));
2507 }
2508
2509 #[test]
2510 fn msg_roundtrip() {
2511 let _log = crate::tests::test_init_log();
2512 for m in (0x009..0x4ff).step_by(0x123) {
2514 let m = Method::new(m);
2515 let classes = vec![
2516 MessageClass::Request,
2517 MessageClass::Indication,
2518 MessageClass::Success,
2519 MessageClass::Error,
2520 ];
2521 for c in classes {
2522 let mtype = MessageType::from_class_method(c, m);
2523 for tid in (0x18..0xff_ffff_ffff_ffff_ffff).step_by(0xfedc_ba98_7654_3210) {
2524 let mut msg = Message::builder(mtype, tid.into(), MessageWriteVec::default());
2525 let attr = RawAttribute::new(1.into(), &[3]);
2526 assert!(msg.add_attribute(&attr).is_ok());
2527 let data = msg.finish();
2528
2529 let msg = Message::from_bytes(&data).unwrap();
2530 let msg_attr = msg.raw_attribute(1.into()).unwrap();
2531 assert_eq!(msg_attr, attr);
2532 assert_eq!(msg.get_type(), mtype);
2533 assert_eq!(msg.transaction_id(), tid.into());
2534 assert_eq!(msg.as_bytes(), &data);
2535 assert_eq!(msg.as_ref(), &data);
2536 }
2537 }
2538 }
2539 }
2540
2541 #[test]
2542 fn unknown_attributes() {
2543 let _log = crate::tests::test_init_log();
2544 let src = Message::builder_request(BINDING, MessageWriteVec::default()).finish();
2545 let src = Message::from_bytes(&src).unwrap();
2546 let msg =
2547 Message::unknown_attributes(&src, &[Software::TYPE], MessageWriteVec::new()).finish();
2548 let msg = Message::from_bytes(&msg).unwrap();
2549 assert_eq!(msg.transaction_id(), src.transaction_id());
2550 assert_eq!(msg.class(), MessageClass::Error);
2551 assert!(msg.has_class(MessageClass::Error));
2552 assert!(!msg.has_class(MessageClass::Success));
2553 assert_eq!(msg.method(), src.method());
2554 assert!(msg.has_method(src.method()));
2555 let err = msg.attribute::<ErrorCode>().unwrap();
2556 assert_eq!(err.code(), 420);
2557 let unknown_attrs = msg.attribute::<UnknownAttributes>().unwrap();
2558 assert!(unknown_attrs.has_attribute(Software::TYPE));
2559 }
2560
2561 #[test]
2562 fn bad_request() {
2563 let _log = crate::tests::test_init_log();
2564 let src = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2565 let src = Message::from_bytes(&src).unwrap();
2566 let msg = Message::bad_request(&src, MessageWriteVec::new());
2567 assert!(msg.has_class(MessageClass::Error));
2568 assert!(!msg.has_class(MessageClass::Success));
2569 assert!(msg.has_method(src.method()));
2570 assert!(!msg.has_method(Method::new(0x111)));
2571 assert!(msg.is_response());
2572 let msg = msg.finish();
2573 let msg = Message::from_bytes(&msg).unwrap();
2574 assert_eq!(msg.transaction_id(), src.transaction_id());
2575 assert_eq!(msg.class(), MessageClass::Error);
2576 assert_eq!(msg.method(), src.method());
2577 let err = msg.attribute::<ErrorCode>().unwrap();
2578 assert_eq!(err.code(), 400);
2579 }
2580
2581 #[test]
2582 fn fingerprint() {
2583 let _log = crate::tests::test_init_log();
2584 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2585 assert!(msg.has_class(MessageClass::Request));
2586 assert!(!msg.has_class(MessageClass::Success));
2587 assert!(msg.has_method(BINDING));
2588 assert!(!msg.has_method(Method::new(0x111)));
2589 let software = Software::new("s").unwrap();
2590 msg.add_attribute(&software).unwrap();
2591 msg.add_fingerprint().unwrap();
2592 let bytes = msg.finish();
2593 let new_msg = Message::from_bytes(&bytes).unwrap();
2595 let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2596 assert_eq!(software.software(), "s");
2597 assert_eq!(offset, 20);
2598 let (offset, _new_fingerprint) =
2599 new_msg.raw_attribute_and_offset(Fingerprint::TYPE).unwrap();
2600 assert_eq!(offset, 28);
2601 }
2602
2603 #[test]
2604 fn integrity() {
2605 let _log = crate::tests::test_init_log();
2606 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2607 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2608 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2609 let software = Software::new("s").unwrap();
2610 msg.add_attribute(&software).unwrap();
2611 msg.add_message_integrity(&credentials, algorithm).unwrap();
2612 let bytes = msg.finish();
2613 let new_msg = Message::from_bytes(&bytes).unwrap();
2615 new_msg.validate_integrity(&credentials).unwrap();
2616 let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2617 assert_eq!(software.software(), "s");
2618 assert_eq!(offset, 20);
2619 }
2620 }
2621
2622 #[test]
2623 fn write_into_short_destination() {
2624 let _log = crate::tests::test_init_log();
2625 const LEN: usize = MessageHeader::LENGTH + 8;
2626 let mut data = [0; LEN - 1];
2627 let mut msg = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
2628 let software = Software::new("s").unwrap();
2629 assert!(
2630 matches!(msg.add_attribute(&software), Err(StunWriteError::TooSmall { expected, actual }) if expected == LEN && actual == LEN - 1)
2631 );
2632 }
2633
2634 #[test]
2635 fn integrity_key() {
2636 let _log = crate::tests::test_init_log();
2637 let credentials1 = ShortTermCredentials::new("pass1".to_owned());
2638 let key1 = MessageIntegrityCredentials::from(credentials1).make_key();
2639 let credentials2 = ShortTermCredentials::new("pass2".to_owned());
2640 let key2 = MessageIntegrityCredentials::from(credentials2).make_key();
2641 assert_eq!(key1, key1);
2642 assert_eq!(key2, key2);
2643 assert_ne!(key1, key2);
2644 }
2645
2646 #[test]
2647 fn add_duplicate_integrity() {
2648 let _log = crate::tests::test_init_log();
2649 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2650 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2651 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
2652 .unwrap();
2653 assert!(matches!(
2654 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2655 Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2656 ));
2657 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2658 .unwrap();
2659 assert!(matches!(
2660 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256),
2661 Err(StunWriteError::AttributeExists(
2662 MessageIntegritySha256::TYPE
2663 ))
2664 ));
2665 let software = Software::new("s").unwrap();
2666 assert!(matches!(
2667 msg.add_attribute(&software),
2668 Err(StunWriteError::MessageIntegrityExists)
2669 ));
2670 }
2671
2672 #[test]
2673 fn add_sha1_integrity_after_sha256() {
2674 let _log = crate::tests::test_init_log();
2675 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2676 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2677 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2678 .unwrap();
2679 assert!(matches!(
2680 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2681 Err(StunWriteError::AttributeExists(
2682 MessageIntegritySha256::TYPE
2683 ))
2684 ));
2685 }
2686
2687 #[test]
2688 fn add_attribute_after_integrity() {
2689 let _log = crate::tests::test_init_log();
2690 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2691 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2692 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2693 msg.add_message_integrity(&credentials, algorithm).unwrap();
2694 let software = Software::new("s").unwrap();
2695 assert!(matches!(
2696 msg.add_attribute(&software),
2697 Err(StunWriteError::MessageIntegrityExists)
2698 ));
2699 }
2700 }
2701
2702 #[test]
2703 fn add_raw_attribute_after_integrity() {
2704 let _log = crate::tests::test_init_log();
2705 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2706 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2707 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2708 msg.add_message_integrity(&credentials, algorithm).unwrap();
2709 let software = Software::new("s").unwrap();
2710 let raw = software.to_raw();
2711 assert!(matches!(
2712 msg.add_attribute(&raw),
2713 Err(StunWriteError::MessageIntegrityExists)
2714 ));
2715 }
2716 }
2717
2718 #[test]
2719 fn add_integrity_after_fingerprint() {
2720 let _log = crate::tests::test_init_log();
2721 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2722 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2723 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2724 msg.add_fingerprint().unwrap();
2725 assert!(matches!(
2726 msg.add_message_integrity(&credentials, algorithm),
2727 Err(StunWriteError::FingerprintExists)
2728 ));
2729 }
2730 }
2731
2732 #[test]
2733 fn duplicate_fingerprint() {
2734 let _log = crate::tests::test_init_log();
2735 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2736 msg.add_fingerprint().unwrap();
2737 assert!(matches!(
2738 msg.add_fingerprint(),
2739 Err(StunWriteError::AttributeExists(Fingerprint::TYPE))
2740 ));
2741 }
2742
2743 #[test]
2744 fn parse_invalid_fingerprint() {
2745 let _log = crate::tests::test_init_log();
2746 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2747 msg.add_fingerprint().unwrap();
2748 let mut bytes = msg.finish();
2749 bytes[24] = 0x80;
2750 bytes[25] = 0x80;
2751 bytes[26] = 0x80;
2752 bytes[27] = 0x80;
2753 assert!(matches!(
2754 Message::from_bytes(&bytes),
2755 Err(StunParseError::FingerprintMismatch)
2756 ));
2757 }
2758
2759 #[test]
2760 fn parse_wrong_magic() {
2761 let _log = crate::tests::test_init_log();
2762 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2763 msg.add_fingerprint().unwrap();
2764 let mut bytes = msg.finish();
2765 bytes[4] = 0x80;
2766 assert!(matches!(
2767 Message::from_bytes(&bytes),
2768 Err(StunParseError::NotStun)
2769 ));
2770 }
2771
2772 #[test]
2773 fn parse_attribute_after_integrity() {
2774 let _log = crate::tests::test_init_log();
2775 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2776 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2777 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2778 msg.add_message_integrity(&credentials, algorithm).unwrap();
2779 let mut bytes = msg.finish();
2780 let software = Software::new("s").unwrap();
2781 let software_bytes = RawAttribute::from(&software).to_bytes();
2782 let software_len = software_bytes.len();
2783 bytes.extend(software_bytes);
2784 bytes[3] += software_len as u8;
2785 let msg = Message::from_bytes(&bytes).unwrap();
2786 assert!(msg.raw_attribute(Software::TYPE).is_none());
2787 }
2788 }
2789
2790 #[test]
2791 fn parse_duplicate_integrity_after_integrity() {
2792 let _log = crate::tests::test_init_log();
2793 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2794 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2795 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2796 msg.add_message_integrity(&credentials, algorithm).unwrap();
2797 add_message_integrity_unchecked(&mut msg, &credentials.make_key(), algorithm);
2799 let bytes = msg.finish();
2800 let integrity_type = match algorithm {
2801 IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2802 IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2803 };
2804 let msg = Message::from_bytes(&bytes).unwrap();
2805 msg.nth_raw_attribute(integrity_type, 0).unwrap();
2806 assert!(msg.nth_raw_attribute(integrity_type, 1).is_none());
2807 }
2808 }
2809
2810 #[test]
2811 fn parse_attribute_after_fingerprint() {
2812 let _log = crate::tests::test_init_log();
2813 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2814 msg.add_fingerprint().unwrap();
2815 let mut bytes = msg.finish();
2816 let software = Software::new("s").unwrap();
2817 let software_bytes = RawAttribute::from(&software).to_bytes();
2818 let software_len = software_bytes.len();
2819 bytes.extend(software_bytes);
2820 bytes[3] += software_len as u8;
2821 let msg = Message::from_bytes(&bytes).unwrap();
2822 assert!(msg.raw_attribute(Fingerprint::TYPE).is_some());
2823 assert!(msg.raw_attribute(Software::TYPE).is_none());
2824 }
2825
2826 #[test]
2827 fn parse_duplicate_fingerprint_after_fingerprint() {
2828 let _log = crate::tests::test_init_log();
2829 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2830 msg.add_fingerprint().unwrap();
2831 add_fingerprint_unchecked(&mut msg);
2832 let bytes = msg.finish();
2833 let msg = Message::from_bytes(&bytes).unwrap();
2834 assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 0).is_some());
2835 assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 1).is_none());
2836 }
2837
2838 #[test]
2839 fn add_attribute_after_fingerprint() {
2840 let _log = crate::tests::test_init_log();
2841 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2842 msg.add_fingerprint().unwrap();
2843 let software = Software::new("s").unwrap();
2844 assert!(matches!(
2845 msg.add_attribute(&software),
2846 Err(StunWriteError::FingerprintExists)
2847 ));
2848 }
2849
2850 #[test]
2851 fn add_raw_attribute_after_fingerprint() {
2852 let _log = crate::tests::test_init_log();
2853 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2854 msg.add_fingerprint().unwrap();
2855 let software = Software::new("s").unwrap();
2856 let raw = software.to_raw();
2857 assert!(matches!(
2858 msg.add_attribute(&raw),
2859 Err(StunWriteError::FingerprintExists)
2860 ));
2861 }
2862
2863 #[test]
2864 fn parse_truncated_message_header() {
2865 let _log = crate::tests::test_init_log();
2866 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2867 msg.add_fingerprint().unwrap();
2868 let bytes = msg.finish();
2869 assert!(matches!(
2870 Message::from_bytes(&bytes[..8]),
2871 Err(StunParseError::Truncated {
2872 expected: 20,
2873 actual: 8
2874 })
2875 ));
2876 }
2877
2878 #[test]
2879 fn parse_truncated_message() {
2880 let _log = crate::tests::test_init_log();
2881 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2882 msg.add_fingerprint().unwrap();
2883 let bytes = msg.finish();
2884 assert!(matches!(
2885 Message::from_bytes(&bytes[..24]),
2886 Err(StunParseError::Truncated {
2887 expected: 28,
2888 actual: 24
2889 })
2890 ));
2891 }
2892
2893 #[test]
2894 fn parse_truncated_message_attribute() {
2895 let _log = crate::tests::test_init_log();
2896 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2897 msg.add_fingerprint().unwrap();
2898 let mut bytes = msg.finish();
2899 bytes[3] = 4;
2901 assert!(matches!(
2902 Message::from_bytes(&bytes[..24]),
2903 Err(StunParseError::Truncated {
2904 expected: 28,
2905 actual: 24
2906 })
2907 ));
2908 }
2909
2910 #[test]
2911 fn parse_attribute_extends_past_message_end() {
2912 let _log = crate::tests::test_init_log();
2913 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2914 msg.add_attribute(&Software::new("a").unwrap()).unwrap();
2915 msg[23] += 1;
2916 let mut bytes = msg.finish();
2917 bytes[3] -= 1;
2918 error!("{bytes:x?}");
2919 error!("{:?}", Message::from_bytes(&bytes[..27]));
2920 assert!(matches!(
2921 Message::from_bytes(&bytes[..27]),
2922 Err(StunParseError::Truncated {
2923 expected: 28,
2924 actual: 27
2925 })
2926 ));
2927 }
2928
2929 #[test]
2930 fn valid_attributes() {
2931 let _log = crate::tests::test_init_log();
2932 let mut src = Message::builder_request(BINDING, MessageWriteVec::new());
2933 let username = Username::new("123").unwrap();
2934 src.add_attribute(&username).unwrap();
2935 let nonce = Nonce::new("nonce").unwrap();
2936 src.add_attribute(&nonce).unwrap();
2937 assert!(!src.has_attribute(Fingerprint::TYPE));
2938 assert!(src.has_attribute(Nonce::TYPE));
2939 let src = src.finish();
2940 let src = Message::from_bytes(&src).unwrap();
2941 assert!(!src.has_attribute(Fingerprint::TYPE));
2942 assert!(src.has_attribute(Nonce::TYPE));
2943
2944 let res = Message::check_attribute_types(
2946 &src,
2947 &[Username::TYPE, Nonce::TYPE],
2948 &[Username::TYPE],
2949 MessageWriteVec::new(),
2950 );
2951 assert!(res.is_none());
2952
2953 let res = Message::check_attribute_types(
2955 &src,
2956 &[Username::TYPE, Nonce::TYPE],
2957 &[Fingerprint::TYPE],
2958 MessageWriteVec::new(),
2959 );
2960 assert!(res.is_some());
2961 let res = res.unwrap();
2962 let res = res.finish();
2963 let res = Message::from_bytes(&res).unwrap();
2964 assert!(res.has_class(MessageClass::Error));
2965 assert!(res.has_method(src.method()));
2966 let err = res.attribute::<ErrorCode>().unwrap();
2967 assert_eq!(err.code(), 400);
2968
2969 let res =
2971 Message::check_attribute_types(&src, &[Username::TYPE], &[], MessageWriteVec::new());
2972 assert!(res.is_some());
2973 let res = res.unwrap();
2974 let data = res.finish();
2975 let res = Message::from_bytes(&data).unwrap();
2976 assert!(res.has_class(MessageClass::Error));
2977 assert!(res.has_method(src.method()));
2978 let err = res.attribute::<ErrorCode>().unwrap();
2979 assert_eq!(err.code(), 420);
2980 let unknown = res.attribute::<UnknownAttributes>().unwrap();
2981 assert!(unknown.has_attribute(Nonce::TYPE));
2982 }
2983
2984 #[test]
2985 fn attributes_iter_with_short_data() {
2986 let _log = crate::tests::test_init_log();
2987 assert_eq!(
2988 MessageAttributesIter::new(&[0x0, 0x1, 0x2, 0x3, 0x4]).next(),
2989 None
2990 );
2991 assert_eq!(
2992 MessageAttributesIter::new(&[
2993 0x0, 0x1, 0x2, 0x3, 0x21, 0x12, 0xa4, 0x42, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
2994 0x10, 0x11, 0x12, 0x13, 0x14,
2995 ])
2996 .next(),
2997 None
2998 );
2999 }
3000
3001 #[test]
3002 fn attributes_iter_software_after_fingerprint_ignored() {
3003 let _log = crate::tests::test_init_log();
3004 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3005 msg.add_fingerprint().unwrap();
3006 let mut bytes = msg.finish();
3007 let software = Software::new("s").unwrap();
3008 let software_bytes = RawAttribute::from(&software).to_bytes();
3009 let software_len = software_bytes.len();
3010 bytes.extend(software_bytes);
3011 bytes[3] += software_len as u8;
3012 let mut it = MessageAttributesIter::new(&bytes);
3013 let (_offset, fingerprint) = it.next().unwrap();
3014 assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
3015 assert_eq!(it.next(), None);
3016 }
3017
3018 #[test]
3019 fn attributes_iter_message_integrities_fingerprint() {
3020 let _log = crate::tests::test_init_log();
3021 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3022 let credentials = ShortTermCredentials::new("pass".to_owned());
3023 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
3024 .unwrap();
3025 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
3026 .unwrap();
3027 msg.add_fingerprint().unwrap();
3028 let mut bytes = msg.finish();
3029 let software = Software::new("s").unwrap();
3030 let software_bytes = RawAttribute::from(&software).to_bytes();
3031 let software_len = software_bytes.len();
3032 bytes.extend(software_bytes);
3033 bytes[3] += software_len as u8;
3034 let mut it = MessageAttributesIter::new(&bytes);
3035 assert_eq!(it.next().unwrap().1.get_type(), MessageIntegrity::TYPE);
3036 assert_eq!(
3037 it.next().unwrap().1.get_type(),
3038 MessageIntegritySha256::TYPE
3039 );
3040 assert_eq!(it.next().unwrap().1.get_type(), Fingerprint::TYPE);
3041 assert_eq!(it.next(), None);
3042 }
3043
3044 #[test]
3045 fn message_parse_multiple_integrities_fingerprint() {
3046 let _log = crate::tests::test_init_log();
3047 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3048 let credentials = ShortTermCredentials::new("pass".to_owned());
3049 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
3050 .unwrap();
3051 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
3052 .unwrap();
3053 msg.add_fingerprint().unwrap();
3054 let mut bytes = msg.finish();
3055 let software = Software::new("s").unwrap();
3056 let software_bytes = RawAttribute::from(&software).to_bytes();
3057 let software_len = software_bytes.len();
3058 bytes.extend(software_bytes);
3059 bytes[3] += software_len as u8;
3060 let msg = Message::from_bytes(&bytes).unwrap();
3061 assert!(msg.has_attribute(MessageIntegrity::TYPE));
3062 assert!(msg.has_attribute(MessageIntegritySha256::TYPE));
3063 assert!(!msg.has_attribute(Software::TYPE));
3064 assert_eq!(
3065 msg.validate_integrity(&credentials.clone().into()).unwrap(),
3066 IntegrityAlgorithm::Sha256
3067 );
3068 }
3069
3070 #[test]
3071 fn attributes_iter_fingerprint_after_fingerprint_ignored() {
3072 let _log = crate::tests::test_init_log();
3073 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3074 msg.add_fingerprint().unwrap();
3075 let mut bytes = msg.finish();
3076 let fingerprint = Fingerprint::new([bytes[bytes.len() - 1].wrapping_sub(1); 4]);
3077 let fingerprint_bytes = RawAttribute::from(&fingerprint).to_bytes();
3078 let fingerprint_len = fingerprint_bytes.len();
3079 bytes.extend(fingerprint_bytes);
3080 bytes[3] += fingerprint_len as u8;
3081 let mut it = MessageAttributesIter::new(&bytes);
3082 let (_offset, fingerprint) = it.next().unwrap();
3083 assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
3084 assert_eq!(it.next(), None);
3085 }
3086
3087 #[test]
3088 fn write_vec_state() {
3089 let _log = crate::tests::test_init_log();
3090 let mut src = Message::builder_request(BINDING, MessageWriteVec::with_capacity(0x10));
3091 assert_eq!(src.len(), 20);
3092 assert_eq!(src[4], 0x21);
3093 let username = Username::new("123").unwrap();
3094 src.add_attribute(&username).unwrap();
3095 let nonce = Nonce::new("nonce").unwrap();
3096 src.add_attribute(&nonce).unwrap();
3097
3098 assert!(src.has_attribute(Username::TYPE));
3099 assert!(src.has_attribute(Nonce::TYPE));
3100 assert_eq!(
3101 src.has_any_attribute(&[Username::TYPE, Nonce::TYPE]),
3102 Some(Username::TYPE)
3103 );
3104 assert_eq!(
3105 src.has_any_attribute(&[Nonce::TYPE, Username::TYPE]),
3106 Some(Username::TYPE)
3107 );
3108 assert!(src.has_class(MessageClass::Request));
3109 assert!(!src.is_response());
3110 assert!(src.has_method(BINDING));
3111 assert!(src.get_type().has_method(BINDING));
3112 assert!(src.get_type().has_class(MessageClass::Request));
3113 assert!(!src.has_method(Method::new(0x111)));
3114 assert!(!src.get_type().has_method(Method::new(0x111)));
3115 assert!(!src.get_type().has_class(MessageClass::Error));
3116 }
3117
3118 #[test]
3119 fn write_mut_slice_success() {
3120 let _log = crate::tests::test_init_log();
3121 let mut data = [0; 64];
3122 let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3123 assert_eq!(src.len(), 20);
3124 assert_eq!(src[4], 0x21);
3125 let username = Username::new("123").unwrap();
3126 src.add_attribute(&username).unwrap();
3127 let nonce = Nonce::new("nonce").unwrap();
3128 src.add_attribute(&nonce).unwrap();
3129 assert!(src.has_attribute(Username::TYPE));
3130 assert_eq!(
3131 src.has_any_attribute(&[Username::TYPE]),
3132 Some(Username::TYPE)
3133 );
3134 assert!(!src.has_attribute(Software::TYPE));
3135 assert_eq!(src.has_any_attribute(&[Realm::TYPE]), None);
3136 assert_eq!(src.mut_data().len(), src.len());
3137 assert_eq!(src.finish(), 40);
3138 let msg = Message::from_bytes(&data[..40]).unwrap();
3139 let u2 = msg.attribute::<Username>().unwrap();
3140 assert_eq!(u2.username(), "123");
3141 let n2 = msg.attribute::<Nonce>().unwrap();
3142 assert_eq!(n2.nonce(), "nonce");
3143 }
3144
3145 #[test]
3146 fn write_mut_slice_too_short() {
3147 let _log = crate::tests::test_init_log();
3148 let mut data = [0; 27];
3149 let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3150 assert!(matches!(
3151 src.add_attribute(&Username::new("123").unwrap()),
3152 Err(StunWriteError::TooSmall {
3153 expected: 28,
3154 actual: 27
3155 })
3156 ));
3157 }
3158
3159 #[test]
3160 #[should_panic(expected = "created from a non-request message")]
3161 fn builder_success_panic() {
3162 let _log = crate::tests::test_init_log();
3163 let msg = Message::builder(
3164 MessageType::from_class_method(MessageClass::Indication, BINDING),
3165 TransactionId::generate(),
3166 MessageWriteVec::new(),
3167 )
3168 .finish();
3169 let msg = Message::from_bytes(&msg).unwrap();
3170 let _builder = Message::builder_success(&msg, MessageWriteVec::new());
3171 }
3172
3173 #[test]
3174 #[should_panic(expected = "created from a non-request message")]
3175 fn builder_error_panic() {
3176 let _log = crate::tests::test_init_log();
3177 let msg = Message::builder(
3178 MessageType::from_class_method(MessageClass::Indication, BINDING),
3179 TransactionId::generate(),
3180 MessageWriteVec::new(),
3181 )
3182 .finish();
3183 let msg = Message::from_bytes(&msg).unwrap();
3184 let _builder = Message::builder_error(&msg, MessageWriteVec::new());
3185 }
3186
3187 #[test]
3188 #[should_panic(expected = "Use add_message_integrity() instead")]
3189 fn builder_add_attribute_integrity_panic() {
3190 let _log = crate::tests::test_init_log();
3191 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3192 let hmac = [2; 20];
3193 let integrity = MessageIntegrity::new(hmac);
3194 msg.add_attribute(&integrity).unwrap();
3195 }
3196
3197 #[test]
3198 #[should_panic(expected = "Use add_message_integrity() instead")]
3199 fn builder_add_raw_attribute_integrity_panic() {
3200 let _log = crate::tests::test_init_log();
3201 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3202 let hmac = [2; 20];
3203 let integrity = MessageIntegrity::new(hmac);
3204 let raw = integrity.to_raw();
3205 msg.add_attribute(&raw).unwrap();
3206 }
3207
3208 #[test]
3209 #[should_panic(expected = "Use add_message_integrity() instead")]
3210 fn builder_add_attribute_integrity_sha256_panic() {
3211 let _log = crate::tests::test_init_log();
3212 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3213 let hmac = [2; 16];
3214 let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3215 msg.add_attribute(&integrity).unwrap();
3216 }
3217
3218 #[test]
3219 #[should_panic(expected = "Use add_message_integrity() instead")]
3220 fn builder_add_raw_attribute_integrity_sha256_panic() {
3221 let _log = crate::tests::test_init_log();
3222 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3223 let hmac = [2; 16];
3224 let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3225 let raw = integrity.to_raw();
3226 msg.add_attribute(&raw).unwrap();
3227 }
3228
3229 #[test]
3230 #[should_panic(expected = "Use add_fingerprint() instead")]
3231 fn builder_add_attribute_fingerprint_panic() {
3232 let _log = crate::tests::test_init_log();
3233 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3234 let fingerprint = [2; 4];
3235 let fingerprint = Fingerprint::new(fingerprint);
3236 msg.add_attribute(&fingerprint).unwrap();
3237 }
3238
3239 #[test]
3240 #[should_panic(expected = "Use add_fingerprint() instead")]
3241 fn builder_add_raw_attribute_fingerprint_panic() {
3242 let _log = crate::tests::test_init_log();
3243 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3244 let fingerprint = [2; 4];
3245 let fingerprint = Fingerprint::new(fingerprint);
3246 let raw = fingerprint.to_raw();
3247 msg.add_attribute(&raw).unwrap();
3248 }
3249
3250 #[test]
3251 fn rfc5769_vector1() {
3252 let _log = crate::tests::test_init_log();
3253 let data = vec![
3255 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, ];
3283 let msg = Message::from_bytes(&data).unwrap();
3284 assert!(msg.has_class(MessageClass::Request));
3285 assert!(msg.has_method(BINDING));
3286 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3287
3288 let mut builder = Message::builder(
3289 MessageType::from_class_method(MessageClass::Request, BINDING),
3290 msg.transaction_id(),
3291 MessageWriteVec::new(),
3292 );
3293
3294 assert!(msg.has_attribute(Software::TYPE));
3296 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3297 assert!(Software::try_from(&raw).is_ok());
3298 let software = Software::try_from(&raw).unwrap();
3299 assert_eq!(software.software(), "STUN test client");
3300 builder.add_attribute(&software).unwrap();
3301
3302 builder
3304 .add_attribute(&RawAttribute::new(0x24.into(), &[0x6e, 0x00, 0x01, 0xff]))
3305 .unwrap();
3306
3307 builder
3309 .add_attribute(&RawAttribute::new(
3310 0x8029.into(),
3311 &[0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36],
3312 ))
3313 .unwrap();
3314
3315 assert!(msg.has_attribute(Username::TYPE));
3317 let raw = msg.raw_attribute(Username::TYPE).unwrap();
3318 assert!(Username::try_from(&raw).is_ok());
3319 let username = Username::try_from(&raw).unwrap();
3320 assert_eq!(username.username(), "evtj:h6vY");
3321 builder.add_attribute(&username).unwrap();
3322
3323 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3325 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3326 });
3327 assert!(matches!(
3328 msg.validate_integrity(&credentials),
3329 Ok(IntegrityAlgorithm::Sha1)
3330 ));
3331 builder
3332 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3333 .unwrap();
3334
3335 assert!(msg.has_attribute(Fingerprint::TYPE));
3337 builder.add_fingerprint().unwrap();
3338
3339 let mut msg_data = builder.finish();
3341 msg_data[73] = 0x20;
3343 msg_data[74] = 0x20;
3344 msg_data[75] = 0x20;
3345 assert_eq!(msg_data[..80], data[..80]);
3348 }
3349
3350 #[test]
3351 fn rfc5769_vector2() {
3352 let _log = crate::tests::test_init_log();
3353 let data = vec![
3355 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, ];
3376
3377 let msg = Message::from_bytes(&data).unwrap();
3378 assert!(msg.has_class(MessageClass::Success));
3379 assert!(msg.has_method(BINDING));
3380 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3381 let mut builder = Message::builder(
3382 MessageType::from_class_method(MessageClass::Success, BINDING),
3383 msg.transaction_id(),
3384 MessageWriteVec::new(),
3385 );
3386
3387 assert!(msg.has_attribute(Software::TYPE));
3389 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3390 assert!(Software::try_from(&raw).is_ok());
3391 let software = Software::try_from(&raw).unwrap();
3392 assert_eq!(software.software(), "test vector");
3393 builder.add_attribute(&software).unwrap();
3394
3395 assert!(msg.has_attribute(XorMappedAddress::TYPE));
3397 let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3398 assert!(XorMappedAddress::try_from(&raw).is_ok());
3399 let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3400 assert_eq!(
3401 xor_mapped_addres.addr(msg.transaction_id()),
3402 "192.0.2.1:32853".parse().unwrap()
3403 );
3404 builder.add_attribute(&xor_mapped_addres).unwrap();
3405
3406 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3408 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3409 });
3410 let ret = msg.validate_integrity(&credentials);
3411 warn!("{:?}", ret);
3412 assert!(matches!(ret, Ok(IntegrityAlgorithm::Sha1)));
3413 builder
3414 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3415 .unwrap();
3416
3417 assert!(msg.has_attribute(Fingerprint::TYPE));
3419 builder.add_fingerprint().unwrap();
3420
3421 let mut msg_data = builder.finish();
3423 msg_data[35] = 0x20;
3425 assert_eq!(msg_data[..52], data[..52]);
3426 }
3427
3428 #[test]
3429 fn rfc5769_vector3() {
3430 let _log = crate::tests::test_init_log();
3431 let data = vec![
3433 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, ];
3457
3458 let msg = Message::from_bytes(&data).unwrap();
3459 assert!(msg.has_class(MessageClass::Success));
3460 assert!(msg.has_method(BINDING));
3461 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3462 let mut builder = Message::builder(
3463 MessageType::from_class_method(MessageClass::Success, BINDING),
3464 msg.transaction_id(),
3465 MessageWriteVec::new(),
3466 );
3467
3468 assert!(msg.has_attribute(Software::TYPE));
3470 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3471 assert!(Software::try_from(&raw).is_ok());
3472 let software = Software::try_from(&raw).unwrap();
3473 assert_eq!(software.software(), "test vector");
3474 builder.add_attribute(&software).unwrap();
3475
3476 assert!(msg.has_attribute(XorMappedAddress::TYPE));
3478 let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3479 assert!(XorMappedAddress::try_from(&raw).is_ok());
3480 let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3481 assert_eq!(
3482 xor_mapped_addres.addr(msg.transaction_id()),
3483 "[2001:db8:1234:5678:11:2233:4455:6677]:32853"
3484 .parse()
3485 .unwrap()
3486 );
3487 builder.add_attribute(&xor_mapped_addres).unwrap();
3488
3489 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3491 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3492 });
3493 assert!(matches!(
3494 msg.validate_integrity(&credentials),
3495 Ok(IntegrityAlgorithm::Sha1)
3496 ));
3497 builder
3498 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3499 .unwrap();
3500
3501 assert!(msg.has_attribute(Fingerprint::TYPE));
3503 builder.add_fingerprint().unwrap();
3504
3505 let mut msg_data = builder.finish();
3507 msg_data[35] = 0x20;
3509 assert_eq!(msg_data[..64], data[..64]);
3510 }
3511
3512 #[test]
3513 fn rfc5769_vector4() {
3514 let _log = crate::tests::test_init_log();
3515 let data = vec![
3517 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, ];
3547
3548 let msg = Message::from_bytes(&data).unwrap();
3549 assert!(msg.has_class(MessageClass::Request));
3550 assert!(msg.has_method(BINDING));
3551 assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3552 let mut builder = Message::builder(
3553 MessageType::from_class_method(MessageClass::Request, BINDING),
3554 msg.transaction_id(),
3555 MessageWriteVec::new(),
3556 );
3557
3558 let long_term = LongTermCredentials {
3559 username: "\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}".to_owned(),
3560 password: "The\u{00AD}M\u{00AA}tr\u{2168}".to_owned(),
3561 realm: "example.org".to_owned(),
3562 };
3563 assert!(msg.has_attribute(Username::TYPE));
3565 let raw = msg.raw_attribute(Username::TYPE).unwrap();
3566 assert!(Username::try_from(&raw).is_ok());
3567 let username = Username::try_from(&raw).unwrap();
3568 assert_eq!(username.username(), &long_term.username);
3569 builder.add_attribute(&username).unwrap();
3570
3571 let expected_nonce = "f//499k954d6OL34oL9FSTvy64sA";
3573 assert!(msg.has_attribute(Nonce::TYPE));
3574 let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3575 assert!(Nonce::try_from(&raw).is_ok());
3576 let nonce = Nonce::try_from(&raw).unwrap();
3577 assert_eq!(nonce.nonce(), expected_nonce);
3578 builder.add_attribute(&nonce).unwrap();
3579
3580 assert!(msg.has_attribute(Realm::TYPE));
3582 let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3583 assert!(Realm::try_from(&raw).is_ok());
3584 let realm = Realm::try_from(&raw).unwrap();
3585 assert_eq!(realm.realm(), long_term.realm());
3586 builder.add_attribute(&realm).unwrap();
3587
3588 assert_eq!(builder.finish()[4..], data[4..92]);
3596 }
3597
3598 #[test]
3599 fn rfc8489_vector1() {
3600 let _log = crate::tests::test_init_log();
3601 let data = vec![
3604 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, ];
3646
3647 let msg = Message::from_bytes(&data).unwrap();
3648 assert!(msg.has_class(MessageClass::Request));
3649 assert!(msg.has_method(BINDING));
3650 assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3651 let mut builder = Message::builder(
3652 MessageType::from_class_method(MessageClass::Success, BINDING),
3653 msg.transaction_id(),
3654 MessageWriteVec::new(),
3655 );
3656
3657 let long_term = LongTermCredentials {
3658 username: "\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}".to_owned(),
3659 password: "The\u{00AD}M\u{00AA}tr\u{2168}".to_owned(),
3660 realm: "example.org".to_owned(),
3661 };
3662 assert!(msg.has_attribute(Userhash::TYPE));
3664 let raw = msg.raw_attribute(Userhash::TYPE).unwrap();
3665 assert!(Userhash::try_from(&raw).is_ok());
3666 let userhash = Userhash::try_from(&raw).unwrap();
3667 builder.add_attribute(&userhash).unwrap();
3668
3669 let expected_nonce = "obMatJos2AAACf//499k954d6OL34oL9FSTvy64sA";
3671 assert!(msg.has_attribute(Nonce::TYPE));
3672 let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3673 assert!(Nonce::try_from(&raw).is_ok());
3674 let nonce = Nonce::try_from(&raw).unwrap();
3675 assert_eq!(nonce.nonce(), expected_nonce);
3676 builder.add_attribute(&nonce).unwrap();
3677
3678 assert!(msg.has_attribute(Realm::TYPE));
3680 let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3681 assert!(Realm::try_from(&raw).is_ok());
3682 let realm = Realm::try_from(&raw).unwrap();
3683 assert_eq!(realm.realm(), long_term.realm);
3684 builder.add_attribute(&realm).unwrap();
3685
3686 assert!(msg.has_attribute(PasswordAlgorithm::TYPE));
3688 let raw = msg.raw_attribute(PasswordAlgorithm::TYPE).unwrap();
3689 assert!(PasswordAlgorithm::try_from(&raw).is_ok());
3690 let algo = PasswordAlgorithm::try_from(&raw).unwrap();
3691 assert_eq!(algo.algorithm(), PasswordAlgorithmValue::SHA256);
3692 builder.add_attribute(&algo).unwrap();
3693
3694 assert_eq!(builder.finish()[4..], data[4..128]);
3702 }
3703}