1#[cfg(feature = "std")]
90use alloc::collections::BTreeMap;
91use alloc::string::String;
92use alloc::sync::Arc;
93use alloc::vec;
94use alloc::vec::Vec;
95use core::convert::TryFrom;
96#[cfg(feature = "std")]
97use std::sync::{Mutex, OnceLock};
98
99use byteorder::{BigEndian, ByteOrder};
100
101use crate::attribute::*;
102
103use tracing::{debug, trace, warn};
104
105use hmac::digest::core_api::CoreWrapper;
106use hmac::digest::CtOutput;
107use hmac::HmacCore;
108
109pub const MAGIC_COOKIE: u32 = 0x2112A442;
111
112#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
114pub struct Method(u16);
115
116impl core::fmt::Display for Method {
117 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118 write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
119 }
120}
121
122#[cfg(feature = "std")]
123static METHOD_NAME_MAP: OnceLock<Mutex<BTreeMap<Method, &'static str>>> = OnceLock::new();
124
125impl Method {
126 #[cfg(feature = "std")]
128 pub fn add_name(self, name: &'static str) {
129 let mut mnames = METHOD_NAME_MAP
130 .get_or_init(Default::default)
131 .lock()
132 .unwrap();
133 mnames.insert(self, name);
134 }
135
136 pub const fn new(val: u16) -> Self {
148 if val >= 0xf000 {
149 panic!("Method value is out of range!");
150 }
151 Self(val)
152 }
153
154 pub fn value(&self) -> u16 {
164 self.0
165 }
166
167 pub fn name(self) -> &'static str {
175 match self {
176 BINDING => "BINDING",
177 _ => {
178 #[cfg(feature = "std")]
179 {
180 let mnames = METHOD_NAME_MAP
181 .get_or_init(Default::default)
182 .lock()
183 .unwrap();
184 if let Some(name) = mnames.get(&self) {
185 return name;
186 }
187 }
188 "unknown"
189 }
190 }
191 }
192}
193
194pub const BINDING: Method = Method::new(0x0001);
197
198#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)]
200#[non_exhaustive]
201pub enum StunParseError {
202 #[error("The provided data is not a STUN message")]
204 NotStun,
205 #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
207 Truncated {
208 expected: usize,
210 actual: usize,
212 },
213 #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
215 TooLarge {
216 expected: usize,
218 actual: usize,
220 },
221 #[error("Missing attribute {}", .0)]
223 MissingAttribute(AttributeType),
224 #[error("An attribute {} was encountered after a message integrity attribute", .0)]
226 AttributeAfterIntegrity(AttributeType),
227 #[error("An attribute {} was encountered after a fingerprint attribute", .0)]
229 AttributeAfterFingerprint(AttributeType),
230 #[error("Fingerprint does not match")]
232 FingerprintMismatch,
233 #[error("The provided data does not match the message")]
235 DataMismatch,
236 #[error("The attribute contains invalid data")]
238 InvalidAttributeData,
239 #[error("Cannot parse with this attribute")]
241 WrongAttributeImplementation,
242}
243
244#[derive(Debug, thiserror::Error)]
246#[non_exhaustive]
247pub enum StunWriteError {
248 #[error("The attribute already exists in the message")]
250 AttributeExists(AttributeType),
251 #[error("The message already contains a fingerprint attribute")]
253 FingerprintExists,
254 #[error("The message already contains a message intregrity attribute")]
256 MessageIntegrityExists,
257 #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
259 TooLarge {
260 expected: usize,
262 actual: usize,
264 },
265 #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
267 TooSmall {
268 expected: usize,
270 actual: usize,
272 },
273 #[error("Failed to compute integrity")]
275 IntegrityFailed,
276 #[error("Out of range input provided")]
278 OutOfRange {
279 value: usize,
281 min: usize,
283 max: usize,
285 },
286}
287
288#[derive(Debug, thiserror::Error, Copy, Clone)]
290pub enum ValidateError {
291 #[error("The message failed to parse the relevant integrity attributes")]
293 Parse(StunParseError),
294 #[error("The message failed integrity checks")]
296 IntegrityFailed,
297}
298
299impl From<StunParseError> for ValidateError {
300 fn from(value: StunParseError) -> Self {
301 Self::Parse(value)
302 }
303}
304
305#[derive(Debug, Clone, PartialEq, Eq)]
307#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
308pub struct LongTermCredentials {
309 username: String,
310 password: String,
311}
312
313impl LongTermCredentials {
314 pub fn new(username: String, password: String) -> Self {
328 Self { username, password }
329 }
330
331 pub fn username(&self) -> &str {
333 &self.username
334 }
335
336 pub fn password(&self) -> &str {
338 &self.password
339 }
340
341 pub fn to_key(&self, realm: String) -> LongTermKeyCredentials {
343 LongTermKeyCredentials {
344 username: self.username.clone(),
345 password: self.password.clone(),
346 realm,
347 }
348 }
349}
350
351#[derive(Debug, Clone, PartialEq, Eq)]
353#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
354pub struct LongTermKeyCredentials {
355 username: String,
356 password: String,
357 realm: String,
358}
359
360impl LongTermKeyCredentials {
361 pub fn new(username: String, password: String, realm: String) -> Self {
377 Self {
378 username,
379 password,
380 realm,
381 }
382 }
383
384 pub fn username(&self) -> &str {
386 &self.username
387 }
388
389 pub fn password(&self) -> &str {
391 &self.password
392 }
393
394 pub fn realm(&self) -> &str {
396 &self.realm
397 }
398
399 pub fn make_key(&self, algorithm: IntegrityAlgorithm) -> IntegrityKey {
401 match algorithm {
402 IntegrityAlgorithm::Sha1 => {
403 use md5::{Digest, Md5};
404 let mut digest = Md5::new();
405 digest.update(self.username.as_bytes());
406 digest.update(":".as_bytes());
407 digest.update(self.realm.as_bytes());
408 digest.update(":".as_bytes());
409 digest.update(self.password.as_bytes());
410 IntegrityKey::new_with_algo(IntegrityAlgorithm::Sha1, digest.finalize().to_vec())
411 }
412 IntegrityAlgorithm::Sha256 => {
413 use sha2::{Digest, Sha256};
414 let mut digest = Sha256::new();
415 digest.update(self.username.as_bytes());
416 digest.update(":".as_bytes());
417 digest.update(self.realm.as_bytes());
418 digest.update(":".as_bytes());
419 digest.update(self.password.as_bytes());
420 IntegrityKey::new_with_algo(IntegrityAlgorithm::Sha256, digest.finalize().to_vec())
421 }
422 }
423 }
424}
425
426#[derive(Debug, Clone, PartialEq, Eq)]
428#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
429pub struct ShortTermCredentials {
430 password: String,
431}
432
433impl ShortTermCredentials {
434 pub fn new(password: String) -> Self {
444 Self { password }
445 }
446
447 pub fn password(&self) -> &str {
449 &self.password
450 }
451
452 pub fn make_key(&self) -> IntegrityKey {
454 IntegrityKey::new(self.password.as_bytes().to_vec())
455 }
456}
457
458#[derive(Debug, Clone, PartialEq, Eq)]
462#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
463pub enum MessageIntegrityCredentials {
464 ShortTerm(ShortTermCredentials),
466 LongTerm(LongTermKeyCredentials),
468}
469
470impl From<LongTermKeyCredentials> for MessageIntegrityCredentials {
471 fn from(value: LongTermKeyCredentials) -> Self {
472 MessageIntegrityCredentials::LongTerm(value)
473 }
474}
475
476impl From<ShortTermCredentials> for MessageIntegrityCredentials {
477 fn from(value: ShortTermCredentials) -> Self {
478 MessageIntegrityCredentials::ShortTerm(value)
479 }
480}
481
482impl MessageIntegrityCredentials {
483 pub fn make_key(&self, algorithm: IntegrityAlgorithm) -> IntegrityKey {
485 match self {
486 MessageIntegrityCredentials::ShortTerm(short) => short.make_key(),
487 MessageIntegrityCredentials::LongTerm(long) => long.make_key(algorithm),
488 }
489 }
490}
491
492type HmacSha1 = hmac::Hmac<sha1::Sha1>;
493type HmacSha256 = hmac::Hmac<sha2::Sha256>;
494
495#[derive(Debug, Clone)]
497pub struct IntegrityKey {
498 key_algorithm: Option<IntegrityAlgorithm>,
499 bytes: Vec<u8>,
500 #[cfg(feature = "std")]
501 sha1: Arc<Mutex<Option<HmacSha1>>>,
502 #[cfg(feature = "std")]
503 sha256: Arc<Mutex<Option<HmacSha256>>>,
504}
505
506impl PartialEq<IntegrityKey> for IntegrityKey {
507 fn eq(&self, other: &Self) -> bool {
508 self.bytes == other.bytes
509 }
510}
511
512impl Eq for IntegrityKey {}
513
514impl IntegrityKey {
515 fn new(bytes: Vec<u8>) -> Self {
516 Self {
517 key_algorithm: None,
518 bytes,
519 #[cfg(feature = "std")]
520 sha1: Default::default(),
521 #[cfg(feature = "std")]
522 sha256: Default::default(),
523 }
524 }
525 fn new_with_algo(key_algorithm: IntegrityAlgorithm, bytes: Vec<u8>) -> Self {
526 let mut ret = Self::new(bytes);
527 ret.key_algorithm = Some(key_algorithm);
528 ret
529 }
530 pub(crate) fn as_bytes(&self) -> &[u8] {
531 &self.bytes
532 }
533
534 pub(crate) fn verify_sha1(&self, data: &[&[u8]], expected: &[u8]) -> bool {
535 if self
536 .key_algorithm
537 .is_some_and(|algo| algo != IntegrityAlgorithm::Sha1)
538 {
539 return false;
540 }
541 use hmac::digest::Output;
542 let computed = self.compute_sha1(data);
543 #[allow(deprecated)]
545 {
546 computed == Output::<sha1::Sha1Core>::from_slice(expected).into()
547 }
548 }
549
550 pub(crate) fn compute_sha1(
551 &self,
552 data: &[&[u8]],
553 ) -> CtOutput<CoreWrapper<HmacCore<CoreWrapper<sha1::Sha1Core>>>> {
554 use hmac::Mac;
555 #[cfg(feature = "std")]
556 let mut sha1 = self.sha1.lock().unwrap();
557 #[cfg(feature = "std")]
558 let hmac = sha1.get_or_insert_with(|| HmacSha1::new_from_slice(self.as_bytes()).unwrap());
559 #[cfg(not(feature = "std"))]
560 let mut hmac = HmacSha1::new_from_slice(self.as_bytes()).unwrap();
561
562 for data in data {
563 hmac.update(data);
564 }
565 #[cfg(feature = "std")]
566 let ret = hmac.finalize_reset();
567 #[cfg(not(feature = "std"))]
568 let ret = hmac.finalize();
569 ret
570 }
571
572 pub(crate) fn verify_sha256(&self, data: &[&[u8]], expected: &[u8]) -> bool {
573 use subtle::ConstantTimeEq;
574 if self
575 .key_algorithm
576 .is_some_and(|algo| algo != IntegrityAlgorithm::Sha256)
577 {
578 return false;
579 }
580 if expected.is_empty() {
581 return false;
582 }
583 let computed = self.compute_sha256(data);
584 if computed.len() < expected.len() {
585 return false;
586 }
587 computed[..expected.len()].ct_eq(expected).into()
588 }
589
590 pub(crate) fn compute_sha256(&self, data: &[&[u8]]) -> [u8; 32] {
591 trace!("computing sha256 using {data:?}");
592 use hmac::Mac;
593 #[cfg(feature = "std")]
594 let mut sha256 = self.sha256.lock().unwrap();
595 #[cfg(feature = "std")]
596 let hmac =
597 sha256.get_or_insert_with(|| HmacSha256::new_from_slice(self.as_bytes()).unwrap());
598 #[cfg(not(feature = "std"))]
599 let mut hmac = HmacSha256::new_from_slice(self.as_bytes()).unwrap();
600
601 for data in data {
602 hmac.update(data);
603 }
604 #[cfg(feature = "std")]
605 let ret = hmac.finalize_reset();
606 #[cfg(not(feature = "std"))]
607 let ret = hmac.finalize();
608 ret.into_bytes().into()
609 }
610}
611
612#[derive(Copy, Clone, Debug, PartialEq, Eq)]
624pub enum MessageClass {
625 Request,
627 Indication,
629 Success,
631 Error,
633}
634
635impl MessageClass {
636 pub fn is_response(self) -> bool {
639 matches!(self, MessageClass::Success | MessageClass::Error)
640 }
641
642 fn to_bits(self) -> u16 {
643 match self {
644 MessageClass::Request => 0x000,
645 MessageClass::Indication => 0x010,
646 MessageClass::Success => 0x100,
647 MessageClass::Error => 0x110,
648 }
649 }
650}
651
652#[derive(Copy, Clone, Debug, PartialEq, Eq)]
654pub struct MessageType(u16);
655
656impl core::fmt::Display for MessageType {
657 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
658 write!(
659 f,
660 "MessageType(class: {:?}, method: {}",
661 self.class(),
662 self.method(),
663 )
664 }
665}
666
667impl MessageType {
668 pub fn from_class_method(class: MessageClass, method: Method) -> Self {
679 let class_bits = MessageClass::to_bits(class);
680 let method = method.value();
681 let method_bits = method & 0xf | (method & 0x70) << 1 | (method & 0xf80) << 2;
682 Self(class_bits | method_bits)
685 }
686
687 pub fn class(self) -> MessageClass {
697 let class = (self.0 & 0x10) >> 4 | (self.0 & 0x100) >> 7;
698 match class {
699 0x0 => MessageClass::Request,
700 0x1 => MessageClass::Indication,
701 0x2 => MessageClass::Success,
702 0x3 => MessageClass::Error,
703 _ => unreachable!(),
704 }
705 }
706
707 pub fn has_class(self, cls: MessageClass) -> bool {
717 self.class() == cls
718 }
719
720 pub fn is_response(self) -> bool {
736 self.class().is_response()
737 }
738
739 pub fn method(self) -> Method {
749 Method::new(self.0 & 0xf | (self.0 & 0xe0) >> 1 | (self.0 & 0x3e00) >> 2)
750 }
751
752 pub fn has_method(self, method: Method) -> bool {
762 self.method() == method
763 }
764
765 pub fn write_into(&self, dest: &mut [u8]) {
767 BigEndian::write_u16(dest, self.0);
768 }
769
770 pub fn to_bytes(self) -> Vec<u8> {
772 let mut ret = vec![0; 2];
773 BigEndian::write_u16(&mut ret[0..2], self.0);
774 ret
775 }
776
777 pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
779 let data = BigEndian::read_u16(data);
780 if data & 0xc000 != 0x0 {
781 return Err(StunParseError::NotStun);
783 }
784 Ok(Self(data))
785 }
786}
787impl TryFrom<&[u8]> for MessageType {
788 type Error = StunParseError;
789
790 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
791 MessageType::from_bytes(value)
792 }
793}
794
795#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
797pub struct TransactionId {
798 id: u128,
799}
800
801impl TransactionId {
802 pub fn generate() -> TransactionId {
804 #[cfg(not(feature = "std"))]
805 {
806 use rand::TryRngCore;
807 let mut dest = [0; 16];
808 rand::rngs::OsRng
809 .try_fill_bytes(&mut dest)
810 .expect("Cannot generate random data");
811 u128::from_be_bytes(dest).into()
812 }
813 #[cfg(feature = "std")]
814 {
815 use rand::Rng;
816 let mut rng = rand::rng();
817 rng.random::<u128>().into()
818 }
819 }
820}
821
822impl From<u128> for TransactionId {
823 fn from(id: u128) -> Self {
824 Self {
825 id: id & 0xffff_ffff_ffff_ffff_ffff_ffff,
826 }
827 }
828}
829impl From<TransactionId> for u128 {
830 fn from(id: TransactionId) -> Self {
831 id.id
832 }
833}
834impl core::fmt::Display for TransactionId {
835 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
836 write!(f, "{:#x}", self.id)
837 }
838}
839
840#[derive(Debug)]
846pub struct MessageHeader {
847 mtype: MessageType,
848 transaction_id: TransactionId,
849 length: u16,
850}
851
852impl MessageHeader {
853 pub const LENGTH: usize = 20;
855
856 pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
869 if data.len() < 20 {
870 return Err(StunParseError::Truncated {
871 expected: 20,
872 actual: data.len(),
873 });
874 }
875 let mtype = MessageType::from_bytes(data)?;
876 let mlength = BigEndian::read_u16(&data[2..]);
877 let tid = BigEndian::read_u128(&data[4..]);
878 let cookie = (tid >> 96) as u32;
879 if cookie != MAGIC_COOKIE {
880 warn!(
881 "malformed cookie constant {:?} != stored data {:?}",
882 MAGIC_COOKIE, cookie
883 );
884 return Err(StunParseError::NotStun);
885 }
886
887 Ok(Self {
888 mtype,
889 transaction_id: tid.into(),
890 length: mlength,
891 })
892 }
893
894 pub fn data_length(&self) -> u16 {
897 self.length
898 }
899
900 pub fn transaction_id(&self) -> TransactionId {
902 self.transaction_id
903 }
904
905 pub fn get_type(&self) -> MessageType {
907 self.mtype
908 }
909
910 fn new(mtype: MessageType, transaction_id: TransactionId, length: u16) -> Self {
911 Self {
912 mtype,
913 transaction_id,
914 length,
915 }
916 }
917
918 fn write_into(&self, dest: &mut [u8]) {
919 self.mtype.write_into(&mut dest[..2]);
920 let transaction: u128 = self.transaction_id.into();
921 let tid = (MAGIC_COOKIE as u128) << 96 | transaction & 0xffff_ffff_ffff_ffff_ffff_ffff;
922 BigEndian::write_u128(&mut dest[4..20], tid);
923 BigEndian::write_u16(&mut dest[2..4], self.length);
924 }
925}
926
927#[derive(Debug, Clone, Copy)]
932pub struct Message<'a> {
933 data: &'a [u8],
934}
935
936impl core::fmt::Display for Message<'_> {
937 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
938 write!(
939 f,
940 "Message(class: {:?}, method: {}, transaction: {}, attributes: ",
941 self.get_type().class(),
942 self.get_type().method(),
943 self.transaction_id()
944 )?;
945 let iter = self.iter_attributes();
946 write!(f, "[")?;
947 for (i, (_offset, a)) in iter.enumerate() {
948 if i > 0 {
949 write!(f, ", ")?;
950 }
951 write!(f, "{a}")?;
952 }
953 write!(f, "]")?;
954 write!(f, ")")
955 }
956}
957
958#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
960pub enum IntegrityAlgorithm {
961 Sha1,
963 Sha256,
965}
966
967impl<'a> Message<'a> {
968 pub fn builder<B: MessageWrite>(
984 mtype: MessageType,
985 transaction_id: TransactionId,
986 mut write: B,
987 ) -> B {
988 let mut data = [0; 20];
989 MessageHeader::new(mtype, transaction_id, 0).write_into(&mut data);
990 write.push_data(&data);
991 write
992 }
993
994 pub fn builder_request<B: MessageWrite>(method: Method, write: B) -> B {
1008 Message::builder(
1009 MessageType::from_class_method(MessageClass::Request, method),
1010 TransactionId::generate(),
1011 write,
1012 )
1013 }
1014
1015 pub fn builder_success<B: MessageWrite>(orig: &Message, write: B) -> B {
1035 if !orig.has_class(MessageClass::Request) {
1036 panic!(
1037 "A success response message was attempted to be created from a non-request message"
1038 );
1039 }
1040 Message::builder(
1041 MessageType::from_class_method(MessageClass::Success, orig.method()),
1042 orig.transaction_id(),
1043 write,
1044 )
1045 }
1046
1047 pub fn builder_error<B: MessageWrite>(orig: &Message, write: B) -> B {
1067 if !orig.has_class(MessageClass::Request) {
1068 panic!(
1069 "An error response message was attempted to be created from a non-request message"
1070 );
1071 }
1072 Message::builder(
1073 MessageType::from_class_method(MessageClass::Error, orig.method()),
1074 orig.transaction_id(),
1075 write,
1076 )
1077 }
1078
1079 pub fn builder_indication<B: MessageWrite>(method: Method, write: B) -> B {
1093 Message::builder(
1094 MessageType::from_class_method(MessageClass::Indication, method),
1095 TransactionId::generate(),
1096 write,
1097 )
1098 }
1099
1100 pub fn get_type(&self) -> MessageType {
1114 MessageType::try_from(&self.data[..2]).unwrap()
1115 }
1116
1117 pub fn class(&self) -> MessageClass {
1129 self.get_type().class()
1130 }
1131
1132 pub fn has_class(&self, cls: MessageClass) -> bool {
1144 self.class() == cls
1145 }
1146
1147 pub fn is_response(&self) -> bool {
1169 self.class().is_response()
1170 }
1171
1172 pub fn method(&self) -> Method {
1184 self.get_type().method()
1185 }
1186
1187 pub fn has_method(&self, method: Method) -> bool {
1200 self.method() == method
1201 }
1202
1203 pub fn transaction_id(&self) -> TransactionId {
1217 BigEndian::read_u128(&self.data[4..]).into()
1218 }
1219
1220 #[tracing::instrument(
1242 name = "message_from_bytes",
1243 level = "trace",
1244 skip(data),
1245 fields(
1246 data.len = data.len()
1247 )
1248 )]
1249 pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
1250 let orig_data = data;
1251
1252 let header = MessageHeader::from_bytes(data)?;
1253 let mlength = header.data_length() as usize;
1254 if mlength + MessageHeader::LENGTH > data.len() {
1255 warn!(
1257 "malformed advertised size {} and data size {} don't match",
1258 mlength + 20,
1259 data.len()
1260 );
1261 return Err(StunParseError::Truncated {
1262 expected: mlength + MessageHeader::LENGTH,
1263 actual: data.len(),
1264 });
1265 }
1266
1267 let ending_attributes = [
1268 MessageIntegrity::TYPE,
1269 MessageIntegritySha256::TYPE,
1270 Fingerprint::TYPE,
1271 ];
1272 let mut seen_ending_attributes = [AttributeType::new(0); 3];
1274 let mut seen_ending_len = 0;
1275 let mut data_offset = MessageHeader::LENGTH;
1276 for attr in MessageRawAttributesIter::new(data) {
1277 let (_offset, attr) = attr.inspect_err(|e| {
1278 warn!("failed to parse message attribute at offset {data_offset}: {e}",);
1279 })?;
1280
1281 if seen_ending_len > 0 && !ending_attributes.contains(&attr.get_type()) {
1284 if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1285 warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1286 return Ok(Message { data: orig_data });
1287 } else {
1288 warn!(
1290 "unexpected attribute {} after MESSAGE_INTEGRITY",
1291 attr.get_type()
1292 );
1293 return Ok(Message { data: orig_data });
1294 }
1295 }
1296
1297 if ending_attributes.contains(&attr.get_type()) {
1298 if seen_ending_attributes.contains(&attr.get_type()) {
1299 if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1300 warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1301 return Ok(Message { data: orig_data });
1302 } else {
1303 warn!(
1305 "unexpected attribute {} after MESSAGE_INTEGRITY",
1306 attr.get_type()
1307 );
1308 return Ok(Message { data: orig_data });
1309 }
1310 } else {
1311 seen_ending_attributes[seen_ending_len] = attr.get_type();
1312 seen_ending_len += 1;
1313 }
1315 }
1316 let padded_len = attr.padded_len();
1317 if attr.get_type() == Fingerprint::TYPE {
1318 let f = Fingerprint::from_raw_ref(&attr)?;
1319 let msg_fingerprint = f.fingerprint();
1320 let mut header = [0; 4];
1321 header[0] = orig_data[0];
1322 header[1] = orig_data[1];
1323 BigEndian::write_u16(
1324 &mut header[2..4],
1325 (data_offset + padded_len - MessageHeader::LENGTH) as u16,
1326 );
1327 let fingerprint_data = &orig_data[4..data_offset];
1328 let calculated_fingerprint = Fingerprint::compute(&[&header, fingerprint_data]);
1329 if &calculated_fingerprint != msg_fingerprint {
1330 warn!(
1331 "fingerprint mismatch {:?} != {:?}",
1332 calculated_fingerprint, msg_fingerprint
1333 );
1334 return Err(StunParseError::FingerprintMismatch);
1335 }
1336 }
1337 data_offset += padded_len;
1338 }
1339 Ok(Message { data: orig_data })
1340 }
1341
1342 pub fn validate_integrity(
1362 &self,
1363 credentials: &MessageIntegrityCredentials,
1364 ) -> Result<IntegrityAlgorithm, ValidateError> {
1365 let raw_sha1 = self.raw_attribute(MessageIntegrity::TYPE);
1366 let raw_sha256 = self.raw_attribute(MessageIntegritySha256::TYPE);
1367 let (algo, msg_hmac) = match (raw_sha1, raw_sha256) {
1368 (_, Some(sha256)) => {
1369 let integrity = MessageIntegritySha256::try_from(&sha256)?;
1370 (IntegrityAlgorithm::Sha256, integrity.hmac().to_vec())
1371 }
1372 (Some(sha1), None) => {
1373 let integrity = MessageIntegrity::try_from(&sha1)?;
1374 (IntegrityAlgorithm::Sha1, integrity.hmac().to_vec())
1375 }
1376 (None, None) => {
1377 return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE).into())
1378 }
1379 };
1380 let key = credentials.make_key(algo);
1381 self.validate_integrity_with_hmac(algo, &msg_hmac, &key)
1382 }
1383
1384 pub fn validate_integrity_with_key(
1386 &self,
1387 key: &IntegrityKey,
1388 ) -> Result<IntegrityAlgorithm, ValidateError> {
1389 let raw_sha1 = self.raw_attribute(MessageIntegrity::TYPE);
1390 let raw_sha256 = self.raw_attribute(MessageIntegritySha256::TYPE);
1391 let (algo, msg_hmac) = if let Some(algo) = key.key_algorithm {
1392 match (algo, raw_sha1, raw_sha256) {
1393 (IntegrityAlgorithm::Sha256, _, Some(sha256)) => {
1394 let integrity = MessageIntegritySha256::try_from(&sha256)?;
1395 (algo, integrity.hmac().to_vec())
1396 }
1397 (IntegrityAlgorithm::Sha1, Some(sha1), _) => {
1398 let integrity = MessageIntegrity::try_from(&sha1)?;
1399 (algo, integrity.hmac().to_vec())
1400 }
1401 _ => return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE).into()),
1402 }
1403 } else {
1404 match (raw_sha1, raw_sha256) {
1405 (_, Some(sha256)) => {
1406 let integrity = MessageIntegritySha256::try_from(&sha256)?;
1407 (IntegrityAlgorithm::Sha256, integrity.hmac().to_vec())
1408 }
1409 (Some(sha1), None) => {
1410 let integrity = MessageIntegrity::try_from(&sha1)?;
1411 (IntegrityAlgorithm::Sha1, integrity.hmac().to_vec())
1412 }
1413 (None, None) => {
1414 return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE).into())
1415 }
1416 }
1417 };
1418 self.validate_integrity_with_hmac(algo, &msg_hmac, key)
1419 }
1420
1421 #[tracing::instrument(
1422 name = "message_validate_integrity_with_hmac",
1423 level = "trace",
1424 skip(self, key, msg_hmac),
1425 fields(
1426 msg.transaction = %self.transaction_id(),
1427 )
1428 )]
1429 fn validate_integrity_with_hmac(
1430 &self,
1431 algo: IntegrityAlgorithm,
1432 msg_hmac: &[u8],
1433 key: &IntegrityKey,
1434 ) -> Result<IntegrityAlgorithm, ValidateError> {
1435 if key.key_algorithm.is_some_and(|key_algo| key_algo != algo) {
1436 debug!(
1437 "Key algorithm ({:?}) does not match algo ({algo:?})",
1438 key.key_algorithm
1439 );
1440 return Err(StunParseError::DataMismatch.into());
1441 }
1442 let data = self.data;
1445 debug_assert!(data.len() >= MessageHeader::LENGTH);
1446 let mut data = &data[MessageHeader::LENGTH..];
1447 let mut data_offset = MessageHeader::LENGTH;
1448 while !data.is_empty() {
1449 let attr = RawAttribute::from_bytes(data)?;
1450 if algo == IntegrityAlgorithm::Sha1 && attr.get_type() == MessageIntegrity::TYPE {
1451 let msg = MessageIntegrity::try_from(&attr)?;
1452 debug_assert!(msg.hmac().as_slice() == msg_hmac);
1453
1454 let mut header = [0; 4];
1457 header[0] = self.data[0];
1458 header[1] = self.data[1];
1459 let hmac_data = &self.data[4..data_offset];
1460 BigEndian::write_u16(
1461 &mut header[2..4],
1462 data_offset as u16 + 24 - MessageHeader::LENGTH as u16,
1463 );
1464 if MessageIntegrity::verify(
1465 &[header.as_slice(), hmac_data],
1466 key,
1467 msg_hmac.try_into().unwrap(),
1468 ) {
1469 return Ok(algo);
1470 } else {
1471 return Err(ValidateError::IntegrityFailed);
1472 }
1473 } else if algo == IntegrityAlgorithm::Sha256
1474 && attr.get_type() == MessageIntegritySha256::TYPE
1475 {
1476 let msg = MessageIntegritySha256::try_from(&attr)?;
1477 debug_assert!(msg.hmac() == msg_hmac);
1478
1479 let mut header = [0; 4];
1482 header[0] = self.data[0];
1483 header[1] = self.data[1];
1484 let hmac_data = &self.data[4..data_offset];
1485 BigEndian::write_u16(
1486 &mut header[2..4],
1487 data_offset as u16 + attr.padded_len() as u16 - MessageHeader::LENGTH as u16,
1488 );
1489 if MessageIntegritySha256::verify(&[&header, hmac_data], key, msg_hmac) {
1490 return Ok(algo);
1491 } else {
1492 return Err(ValidateError::IntegrityFailed);
1493 }
1494 }
1495 let padded_len = attr.padded_len();
1496 debug_assert!(padded_len <= data.len());
1498 data = &data[padded_len..];
1499 data_offset += padded_len;
1500 }
1501
1502 unreachable!();
1505 }
1506
1507 pub fn nth_raw_attribute(&self, atype: AttributeType, n: usize) -> Option<RawAttribute<'_>> {
1526 self.nth_raw_attribute_and_offset(atype, n)
1527 .map(|(_offset, attr)| attr)
1528 }
1529
1530 pub fn raw_attribute(&self, atype: AttributeType) -> Option<RawAttribute<'_>> {
1534 self.nth_raw_attribute(atype, 0)
1535 }
1536
1537 #[tracing::instrument(
1559 name = "message_nth_raw_attribute_and_offset",
1560 level = "trace",
1561 skip(self, atype),
1562 fields(
1563 msg.transaction = %self.transaction_id(),
1564 attribute_type = %atype,
1565 )
1566 )]
1567 pub fn nth_raw_attribute_and_offset(
1568 &self,
1569 atype: AttributeType,
1570 n: usize,
1571 ) -> Option<(usize, RawAttribute<'_>)> {
1572 if let Some((offset, attr)) = self
1573 .iter_attributes()
1574 .filter(|(_offset, attr)| attr.get_type() == atype)
1575 .nth(n)
1576 {
1577 trace!("found attribute at offset: {offset}");
1578 Some((offset, attr))
1579 } else {
1580 trace!("could not find attribute");
1581 None
1582 }
1583 }
1584
1585 pub fn raw_attribute_and_offset(
1590 &self,
1591 atype: AttributeType,
1592 ) -> Option<(usize, RawAttribute<'_>)> {
1593 self.nth_raw_attribute_and_offset(atype, 0)
1594 }
1595
1596 pub fn nth_attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1618 &'a self,
1619 n: usize,
1620 ) -> Result<A, StunParseError> {
1621 self.nth_attribute_and_offset(n).map(|(_offset, attr)| attr)
1622 }
1623
1624 pub fn attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1628 &'a self,
1629 ) -> Result<A, StunParseError> {
1630 self.nth_attribute(0)
1631 }
1632
1633 pub fn nth_attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1659 &'a self,
1660 n: usize,
1661 ) -> Result<(usize, A), StunParseError> {
1662 self.nth_raw_attribute_and_offset(A::TYPE, n)
1663 .ok_or(StunParseError::MissingAttribute(A::TYPE))
1664 .and_then(|(offset, raw)| A::from_raw(raw).map(|attr| (offset, attr)))
1665 }
1666
1667 pub fn attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1672 &'a self,
1673 ) -> Result<(usize, A), StunParseError> {
1674 self.nth_attribute_and_offset(0)
1675 }
1676
1677 pub fn iter_attributes(&self) -> impl Iterator<Item = (usize, RawAttribute<'_>)> {
1679 MessageAttributesIter::new(self.data)
1680 }
1681
1682 #[tracing::instrument(
1731 level = "trace",
1732 skip(msg, write),
1733 fields(
1734 msg.transaction = %msg.transaction_id(),
1735 )
1736 )]
1737 pub fn check_attribute_types<B: MessageWrite>(
1738 msg: &Message,
1739 supported: &[AttributeType],
1740 required_in_msg: &[AttributeType],
1741 write: B,
1742 ) -> Option<B> {
1743 let unsupported: Vec<AttributeType> = msg
1745 .iter_attributes()
1746 .map(|(_offset, a)| a.get_type())
1747 .filter(|at| at.comprehension_required() && !supported.contains(at))
1749 .collect();
1750 if !unsupported.is_empty() {
1751 warn!(
1752 "Message contains unknown comprehension required attributes {:?}, returning unknown attributes",
1753 unsupported
1754 );
1755 return Some(Message::unknown_attributes(msg, &unsupported, write));
1756 }
1757 let has_required_attribute_missing = required_in_msg
1758 .iter()
1759 .any(|&at| {
1761 !msg.iter_attributes()
1762 .map(|(_offset, a)| a.get_type())
1763 .any(|a| a == at)
1764 });
1765 if has_required_attribute_missing {
1766 warn!("Message is missing required attributes, returning bad request");
1767 return Some(Message::bad_request(msg, write));
1768 }
1769 None
1770 }
1771
1772 pub fn unknown_attributes<B: MessageWrite>(
1793 src: &Message,
1794 attributes: &[AttributeType],
1795 write: B,
1796 ) -> B {
1797 let mut out = Message::builder_error(src, write);
1798 let software = Software::new("stun-types").unwrap();
1799 out.add_attribute(&software).unwrap();
1800 let error = ErrorCode::new(420, "Unknown Attributes").unwrap();
1801 out.add_attribute(&error).unwrap();
1802 let unknown = UnknownAttributes::new(attributes);
1803 if !attributes.is_empty() {
1804 out.add_attribute(&unknown).unwrap();
1805 }
1806 out
1807 }
1808
1809 pub fn bad_request<B: MessageWrite>(src: &Message, write: B) -> B {
1827 let mut out = Message::builder_error(src, write);
1828 let software = Software::new("stun-types").unwrap();
1829 out.add_attribute(&software).unwrap();
1830 let error = ErrorCode::new(400, "Bad Request").unwrap();
1831 out.add_attribute(&error).unwrap();
1832 out
1833 }
1834
1835 pub fn has_attribute(&self, atype: AttributeType) -> bool {
1851 self.iter_attributes()
1852 .any(|(_offset, attr)| attr.get_type() == atype)
1853 }
1854
1855 pub fn as_bytes(&self) -> &[u8] {
1857 self.data
1858 }
1859}
1860impl<'a> TryFrom<&'a [u8]> for Message<'a> {
1861 type Error = StunParseError;
1862
1863 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
1864 Message::from_bytes(value)
1865 }
1866}
1867
1868impl AsRef<[u8]> for Message<'_> {
1869 fn as_ref(&self) -> &[u8] {
1870 self.data
1871 }
1872}
1873
1874#[derive(Debug)]
1875struct MessageRawAttributesIter<'a> {
1876 data: &'a [u8],
1877 data_i: usize,
1878}
1879
1880impl<'a> MessageRawAttributesIter<'a> {
1881 fn new(data: &'a [u8]) -> Self {
1882 Self {
1883 data,
1884 data_i: MessageHeader::LENGTH,
1885 }
1886 }
1887}
1888
1889impl<'a> Iterator for MessageRawAttributesIter<'a> {
1890 type Item = Result<(usize, RawAttribute<'a>), StunParseError>;
1891
1892 fn next(&mut self) -> Option<Self::Item> {
1893 if self.data_i >= self.data.len() {
1894 return None;
1895 }
1896
1897 match RawAttribute::from_bytes(&self.data[self.data_i..]) {
1898 Ok(attr) => {
1899 let padded_len = attr.padded_len();
1900 self.data_i += padded_len;
1901 if self.data_i > self.data.len() {
1902 warn!(
1903 "attribute {} extends past the end of the data",
1904 attr.get_type()
1905 );
1906 return Some(Err(StunParseError::Truncated {
1907 expected: self.data_i,
1908 actual: self.data.len(),
1909 }));
1910 }
1911 Some(Ok((self.data_i - padded_len, attr)))
1912 }
1913 Err(e) => {
1914 let offset = self.data_i;
1915 self.data_i = self.data.len();
1916 let e = match e {
1917 StunParseError::Truncated { expected, actual } => StunParseError::Truncated {
1918 expected: expected + 4 + offset,
1919 actual: actual + 4 + offset,
1920 },
1921 StunParseError::TooLarge { expected, actual } => StunParseError::TooLarge {
1922 expected: expected + 4 + offset,
1923 actual: actual + 4 + offset,
1924 },
1925 e => e,
1926 };
1927 Some(Err(e))
1928 }
1929 }
1930 }
1931}
1932
1933#[doc(hidden)]
1934#[derive(Debug)]
1935pub struct MessageAttributesIter<'a> {
1936 header_parsed: bool,
1937 inner: MessageRawAttributesIter<'a>,
1938 last_attr_type: AttributeType,
1939 seen_message_integrity: bool,
1940}
1941
1942impl<'a> MessageAttributesIter<'a> {
1943 pub fn new(data: &'a [u8]) -> Self {
1952 Self {
1953 header_parsed: false,
1954 inner: MessageRawAttributesIter::new(data),
1955 seen_message_integrity: false,
1956 last_attr_type: AttributeType::new(0),
1957 }
1958 }
1959}
1960
1961impl<'a> Iterator for MessageAttributesIter<'a> {
1962 type Item = (usize, RawAttribute<'a>);
1963
1964 fn next(&mut self) -> Option<Self::Item> {
1965 if self.last_attr_type == Fingerprint::TYPE {
1967 return None;
1968 }
1969
1970 if !self.header_parsed {
1971 let Ok(hdr) = MessageHeader::from_bytes(self.inner.data) else {
1972 self.last_attr_type = Fingerprint::TYPE;
1973 return None;
1974 };
1975 if hdr.data_length() as usize + MessageHeader::LENGTH > self.inner.data.len() {
1976 self.last_attr_type = Fingerprint::TYPE;
1977 return None;
1978 }
1979 self.header_parsed = true;
1980 }
1981
1982 let (offset, attr) = self.inner.next()?.ok()?;
1983 let attr_type = attr.get_type();
1984 if self.seen_message_integrity {
1985 if self.last_attr_type != Fingerprint::TYPE && attr_type == Fingerprint::TYPE {
1986 self.last_attr_type = attr_type;
1987 return Some((offset, attr));
1988 }
1989 if self.last_attr_type == MessageIntegrity::TYPE
1990 && attr_type == MessageIntegritySha256::TYPE
1991 {
1992 self.last_attr_type = attr_type;
1993 return Some((offset, attr));
1994 }
1995 self.last_attr_type = Fingerprint::TYPE;
1996 return None;
1997 }
1998 if attr.get_type() == MessageIntegrity::TYPE
1999 || attr.get_type() == MessageIntegritySha256::TYPE
2000 || attr.get_type() == Fingerprint::TYPE
2001 {
2002 self.seen_message_integrity = true;
2003 }
2004 self.last_attr_type = attr.get_type();
2005
2006 Some((offset, attr))
2007 }
2008}
2009
2010#[allow(clippy::len_without_is_empty)]
2011pub trait MessageWrite {
2013 type Output;
2015 fn max_size(&self) -> Option<usize> {
2018 None
2019 }
2020
2021 fn mut_data(&mut self) -> &mut [u8];
2023 fn data(&self) -> &[u8];
2025 fn len(&self) -> usize;
2027 fn push_data(&mut self, data: &[u8]);
2029 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite);
2031
2032 fn has_attribute(&self, atype: AttributeType) -> bool;
2034
2035 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType>;
2038
2039 fn finish(self) -> Self::Output;
2041}
2042
2043pub trait MessageWriteExt: MessageWrite {
2045 fn get_type(&self) -> MessageType {
2057 MessageType::from_bytes(self.data()).unwrap()
2058 }
2059
2060 fn class(&self) -> MessageClass {
2072 self.get_type().class()
2073 }
2074
2075 fn has_class(&self, cls: MessageClass) -> bool {
2087 self.class() == cls
2088 }
2089
2090 fn is_response(&self) -> bool {
2112 self.class().is_response()
2113 }
2114
2115 fn method(&self) -> Method {
2127 self.get_type().method()
2128 }
2129
2130 fn has_method(&self, method: Method) -> bool {
2143 self.method() == method
2144 }
2145
2146 fn transaction_id(&self) -> TransactionId {
2160 BigEndian::read_u128(&self.data()[4..]).into()
2161 }
2162
2163 fn add_message_integrity(
2198 &mut self,
2199 credentials: &MessageIntegrityCredentials,
2200 algorithm: IntegrityAlgorithm,
2201 ) -> Result<(), StunWriteError> {
2202 let key = credentials.make_key(algorithm);
2203 self.add_message_integrity_with_key(&key, algorithm)
2204 }
2205
2206 #[tracing::instrument(
2208 name = "message_add_integrity_with_key",
2209 level = "trace",
2210 err,
2211 skip(self),
2212 fields(
2213 msg.transaction = %self.transaction_id(),
2214 )
2215 )]
2216 fn add_message_integrity_with_key(
2217 &mut self,
2218 key: &IntegrityKey,
2219 algorithm: IntegrityAlgorithm,
2220 ) -> Result<(), StunWriteError> {
2221 let mut atypes = [AttributeType::new(0); 3];
2222 let mut i = 0;
2223 atypes[i] = match algorithm {
2224 IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2225 IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2226 };
2227 i += 1;
2228 if algorithm == IntegrityAlgorithm::Sha1 {
2229 atypes[i] = MessageIntegritySha256::TYPE;
2230 i += 1;
2231 }
2232 atypes[i] = Fingerprint::TYPE;
2233 i += 1;
2234
2235 match self.has_any_attribute(&atypes[..i]) {
2236 Some(MessageIntegrity::TYPE) => {
2238 return Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2239 }
2240 Some(MessageIntegritySha256::TYPE) => {
2241 return Err(StunWriteError::AttributeExists(
2242 MessageIntegritySha256::TYPE,
2243 ));
2244 }
2245 Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2246 _ => (),
2247 }
2248 match algorithm {
2249 IntegrityAlgorithm::Sha1 => {
2250 check_attribute_can_fit(self, &MessageIntegrity::new([0; 20]))?
2251 }
2252 IntegrityAlgorithm::Sha256 => {
2253 check_attribute_can_fit(self, &MessageIntegritySha256::new(&[0; 32]).unwrap())?
2254 }
2255 };
2256
2257 add_message_integrity_unchecked(self, key, algorithm);
2258
2259 Ok(())
2260 }
2261
2262 #[tracing::instrument(
2280 name = "message_add_fingerprint",
2281 level = "trace",
2282 skip(self),
2283 fields(
2284 msg.transaction = %self.transaction_id(),
2285 )
2286 )]
2287 fn add_fingerprint(&mut self) -> Result<(), StunWriteError> {
2288 if self.has_attribute(Fingerprint::TYPE) {
2289 return Err(StunWriteError::AttributeExists(Fingerprint::TYPE));
2290 }
2291
2292 check_attribute_can_fit(self, &Fingerprint::new([0; 4]))?;
2293 add_fingerprint_unchecked(self);
2294
2295 Ok(())
2296 }
2297
2298 #[tracing::instrument(
2327 name = "message_add_attribute",
2328 level = "trace",
2329 err,
2330 skip(self, attr),
2331 fields(
2332 msg.transaction = %self.transaction_id(),
2333 )
2334 )]
2335 fn add_attribute(&mut self, attr: &dyn AttributeWrite) -> Result<(), StunWriteError> {
2336 let ty = attr.get_type();
2337 match ty {
2338 MessageIntegrity::TYPE => {
2339 panic!("Cannot write MessageIntegrity with `add_attribute`. Use add_message_integrity() instead");
2340 }
2341 MessageIntegritySha256::TYPE => {
2342 panic!("Cannot write MessageIntegritySha256 with `add_attribute`. Use add_message_integrity() instead");
2343 }
2344 Fingerprint::TYPE => {
2345 panic!(
2346 "Cannot write Fingerprint with `add_attribute`. Use add_fingerprint() instead"
2347 );
2348 }
2349 _ => (),
2350 }
2351 match self.has_any_attribute(&[
2352 MessageIntegrity::TYPE,
2353 MessageIntegritySha256::TYPE,
2354 Fingerprint::TYPE,
2355 ]) {
2356 Some(MessageIntegrity::TYPE) => return Err(StunWriteError::MessageIntegrityExists),
2358 Some(MessageIntegritySha256::TYPE) => {
2359 return Err(StunWriteError::MessageIntegrityExists)
2360 }
2361 Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2362 _ => (),
2363 }
2364 check_attribute_can_fit(self, attr)?;
2365 self.push_attribute_unchecked(attr);
2366 Ok(())
2367 }
2368}
2369
2370impl<T: MessageWrite> MessageWriteExt for T {}
2371
2372#[derive(Debug, Default)]
2374pub struct MessageWriteVec {
2375 output: Vec<u8>,
2376 attributes: smallvec::SmallVec<[AttributeType; 16]>,
2377}
2378
2379impl MessageWriteVec {
2380 pub fn new() -> Self {
2382 Self::default()
2383 }
2384
2385 pub fn with_capacity(capacity: usize) -> Self {
2387 Self {
2388 output: Vec::with_capacity(capacity),
2389 attributes: Default::default(),
2390 }
2391 }
2392}
2393
2394impl core::ops::Deref for MessageWriteVec {
2395 type Target = Vec<u8>;
2396 fn deref(&self) -> &Self::Target {
2397 &self.output
2398 }
2399}
2400
2401impl core::ops::DerefMut for MessageWriteVec {
2402 fn deref_mut(&mut self) -> &mut Self::Target {
2403 &mut self.output
2404 }
2405}
2406
2407impl MessageWrite for MessageWriteVec {
2408 type Output = Vec<u8>;
2409
2410 fn mut_data(&mut self) -> &mut [u8] {
2411 &mut self.output
2412 }
2413
2414 fn data(&self) -> &[u8] {
2415 &self.output
2416 }
2417
2418 fn len(&self) -> usize {
2419 self.output.len()
2420 }
2421
2422 fn push_data(&mut self, data: &[u8]) {
2423 self.output.extend(data)
2424 }
2425
2426 fn finish(self) -> Self::Output {
2427 self.output
2428 }
2429
2430 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2431 let offset = self.output.len();
2432 let padded_len = attr.padded_len();
2433 let expected = offset + padded_len;
2434 BigEndian::write_u16(
2435 &mut self.output[2..4],
2436 (expected - MessageHeader::LENGTH) as u16,
2437 );
2438 self.output.resize(expected, 0);
2439 attr.write_into_unchecked(&mut self.output[offset..]);
2440 self.attributes.push(attr.get_type());
2441 }
2442
2443 fn has_attribute(&self, atype: AttributeType) -> bool {
2444 self.attributes.contains(&atype)
2445 }
2446
2447 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2448 self.attributes
2449 .iter()
2450 .find(|&typ| atypes.contains(typ))
2451 .cloned()
2452 }
2453}
2454
2455#[derive(Debug, Default)]
2457pub struct MessageWriteMutSlice<'a> {
2458 output: &'a mut [u8],
2459 offset: usize,
2460 attributes: smallvec::SmallVec<[AttributeType; 16]>,
2461}
2462
2463impl<'a> MessageWriteMutSlice<'a> {
2464 pub fn new(data: &'a mut [u8]) -> Self {
2466 Self {
2467 output: data,
2468 offset: 0,
2469 attributes: Default::default(),
2470 }
2471 }
2472}
2473
2474impl core::ops::Deref for MessageWriteMutSlice<'_> {
2475 type Target = [u8];
2476 fn deref(&self) -> &Self::Target {
2477 self.output
2478 }
2479}
2480
2481impl core::ops::DerefMut for MessageWriteMutSlice<'_> {
2482 fn deref_mut(&mut self) -> &mut Self::Target {
2483 self.output
2484 }
2485}
2486
2487impl<'a> MessageWrite for MessageWriteMutSlice<'a> {
2488 type Output = usize;
2489
2490 fn max_size(&self) -> Option<usize> {
2491 Some(self.output.len())
2492 }
2493
2494 fn mut_data(&mut self) -> &mut [u8] {
2495 &mut self.output[..self.offset]
2496 }
2497
2498 fn data(&self) -> &[u8] {
2499 &self.output[..self.offset]
2500 }
2501
2502 fn len(&self) -> usize {
2503 self.offset
2504 }
2505
2506 fn push_data(&mut self, data: &[u8]) {
2507 let len = data.len();
2508 self.output[self.offset..self.offset + len].copy_from_slice(data);
2509 self.offset += len;
2510 }
2511
2512 fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2513 let padded_len = attr.padded_len();
2514 let expected = self.offset + padded_len;
2515 BigEndian::write_u16(
2516 &mut self.output[2..4],
2517 (expected - MessageHeader::LENGTH) as u16,
2518 );
2519 self.attributes.push(attr.get_type());
2520 attr.write_into(&mut self.output[self.offset..self.offset + padded_len])
2521 .unwrap();
2522 self.offset += padded_len;
2523 }
2524
2525 fn finish(self) -> Self::Output {
2526 self.offset
2527 }
2528
2529 fn has_attribute(&self, atype: AttributeType) -> bool {
2530 self.attributes.contains(&atype)
2531 }
2532
2533 fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2534 self.attributes
2535 .iter()
2536 .find(|&typ| atypes.contains(typ))
2537 .cloned()
2538 }
2539}
2540
2541fn check_attribute_can_fit<O, T: MessageWrite<Output = O> + ?Sized>(
2542 this: &mut T,
2543 attr: &dyn AttributeWrite,
2544) -> Result<usize, StunWriteError> {
2545 let len = attr.padded_len();
2546 let out_data = this.data();
2547 if out_data.len() < MessageHeader::LENGTH {
2548 return Err(StunWriteError::TooSmall {
2549 expected: 20,
2550 actual: out_data.len(),
2551 });
2552 }
2553 let expected = BigEndian::read_u16(&out_data[2..4]) as usize + MessageHeader::LENGTH + len;
2554 if let Some(max) = this.max_size() {
2555 if max < expected {
2556 return Err(StunWriteError::TooSmall {
2557 expected,
2558 actual: max,
2559 });
2560 }
2561 }
2562 Ok(expected)
2563}
2564
2565fn add_message_integrity_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(
2566 this: &mut T,
2567 key: &IntegrityKey,
2568 algorithm: IntegrityAlgorithm,
2569) {
2570 match algorithm {
2573 IntegrityAlgorithm::Sha1 => {
2574 this.push_attribute_unchecked(&MessageIntegrity::new([0; 20]));
2575 let len = this.len();
2576 let data = this.mut_data();
2577 let integrity = MessageIntegrity::compute(&[&data[..len - 24]], key).unwrap();
2578 data[len - 20..].copy_from_slice(&integrity);
2579 }
2580 IntegrityAlgorithm::Sha256 => {
2581 this.push_attribute_unchecked(&MessageIntegritySha256::new(&[0; 32]).unwrap());
2582 let len = this.len();
2583 let data = this.mut_data();
2584 let integrity = MessageIntegritySha256::compute(&[&data[..len - 36]], key).unwrap();
2585 data[len - 32..].copy_from_slice(&integrity);
2586 }
2587 }
2588}
2589
2590fn add_fingerprint_unchecked<O, T: MessageWrite<Output = O> + ?Sized>(this: &mut T) {
2591 this.push_attribute_unchecked(&Fingerprint::new([0; 4]));
2594 let len = this.len();
2595 let data = this.mut_data();
2596 let fingerprint = Fingerprint::compute(&[&data[..len - 8]]);
2597 let fingerprint = Fingerprint::new(fingerprint);
2598 fingerprint.write_into(&mut data[len - 8..]).unwrap();
2599}
2600
2601#[cfg(test)]
2602mod tests {
2603 use alloc::borrow::ToOwned;
2604 use precis_profiles::precis_core::profile::Profile;
2605 use tracing::error;
2606
2607 use super::*;
2608
2609 #[test]
2610 #[should_panic(expected = "Method value is out of range")]
2611 fn method_value_out_of_range() {
2612 let _log = crate::tests::test_init_log();
2613 Method::new(0xf000);
2614 }
2615
2616 #[test]
2617 #[cfg(feature = "std")]
2618 fn method_name() {
2619 let _log = crate::tests::test_init_log();
2620 assert_eq!(BINDING.name(), "BINDING");
2621 let method = Method::new(0x111);
2622 method.add_name("SOME-NAME");
2623 assert_eq!(method.name(), "SOME-NAME");
2624 assert_eq!(Method::new(0x112).name(), "unknown");
2625 }
2626
2627 #[test]
2628 fn msg_type_roundtrip() {
2629 let _log = crate::tests::test_init_log();
2630 for m in 0..0xfff {
2632 let m = Method::new(m);
2633 let classes = vec![
2634 MessageClass::Request,
2635 MessageClass::Indication,
2636 MessageClass::Success,
2637 MessageClass::Error,
2638 ];
2639 for c in classes {
2640 let mtype = MessageType::from_class_method(c, m);
2641 trace!("{mtype}");
2642 assert_eq!(mtype.class(), c);
2643 assert!(mtype.has_class(c));
2644 assert_eq!(mtype.method(), m);
2645 assert!(mtype.has_method(m));
2646 let bytes = mtype.to_bytes();
2647 let ptype = MessageType::from_bytes(&bytes).unwrap();
2648 assert_eq!(mtype, ptype);
2649 }
2650 }
2651 }
2652
2653 #[test]
2654 fn msg_type_not_stun() {
2655 assert!(matches!(
2656 MessageType::from_bytes(&[0xc0, 0x00]),
2657 Err(StunParseError::NotStun)
2658 ));
2659 }
2660
2661 #[test]
2662 fn msg_roundtrip() {
2663 let _log = crate::tests::test_init_log();
2664 for m in (0x009..0x4ff).step_by(0x123) {
2666 let m = Method::new(m);
2667 let classes = vec![
2668 MessageClass::Request,
2669 MessageClass::Indication,
2670 MessageClass::Success,
2671 MessageClass::Error,
2672 ];
2673 for c in classes {
2674 let mtype = MessageType::from_class_method(c, m);
2675 for tid in (0x18..0xff_ffff_ffff_ffff_ffff).step_by(0xfedc_ba98_7654_3210) {
2676 let mut msg = Message::builder(mtype, tid.into(), MessageWriteVec::default());
2677 let attr = RawAttribute::new(1.into(), &[3]);
2678 assert!(msg.add_attribute(&attr).is_ok());
2679 let data = msg.finish();
2680
2681 let msg = Message::from_bytes(&data).unwrap();
2682 let msg_attr = msg.raw_attribute(1.into()).unwrap();
2683 assert_eq!(msg_attr, attr);
2684 assert_eq!(msg.get_type(), mtype);
2685 assert_eq!(msg.transaction_id(), tid.into());
2686 assert_eq!(msg.as_bytes(), &data);
2687 assert_eq!(msg.as_ref(), &data);
2688 }
2689 }
2690 }
2691 }
2692
2693 #[test]
2694 fn unknown_attributes() {
2695 let _log = crate::tests::test_init_log();
2696 let src = Message::builder_request(BINDING, MessageWriteVec::default()).finish();
2697 let src = Message::from_bytes(&src).unwrap();
2698 let msg =
2699 Message::unknown_attributes(&src, &[Software::TYPE], MessageWriteVec::new()).finish();
2700 let msg = Message::from_bytes(&msg).unwrap();
2701 assert_eq!(msg.transaction_id(), src.transaction_id());
2702 assert_eq!(msg.class(), MessageClass::Error);
2703 assert!(msg.has_class(MessageClass::Error));
2704 assert!(!msg.has_class(MessageClass::Success));
2705 assert_eq!(msg.method(), src.method());
2706 assert!(msg.has_method(src.method()));
2707 let err = msg.attribute::<ErrorCode>().unwrap();
2708 assert_eq!(err.code(), 420);
2709 let unknown_attrs = msg.attribute::<UnknownAttributes>().unwrap();
2710 assert!(unknown_attrs.has_attribute(Software::TYPE));
2711 }
2712
2713 #[test]
2714 fn bad_request() {
2715 let _log = crate::tests::test_init_log();
2716 let src = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2717 let src = Message::from_bytes(&src).unwrap();
2718 let msg = Message::bad_request(&src, MessageWriteVec::new());
2719 assert!(msg.has_class(MessageClass::Error));
2720 assert!(!msg.has_class(MessageClass::Success));
2721 assert!(msg.has_method(src.method()));
2722 assert!(!msg.has_method(Method::new(0x111)));
2723 assert!(msg.is_response());
2724 let msg = msg.finish();
2725 let msg = Message::from_bytes(&msg).unwrap();
2726 assert_eq!(msg.transaction_id(), src.transaction_id());
2727 assert_eq!(msg.class(), MessageClass::Error);
2728 assert_eq!(msg.method(), src.method());
2729 let err = msg.attribute::<ErrorCode>().unwrap();
2730 assert_eq!(err.code(), 400);
2731 }
2732
2733 #[test]
2734 fn fingerprint() {
2735 let _log = crate::tests::test_init_log();
2736 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2737 assert!(msg.has_class(MessageClass::Request));
2738 assert!(!msg.has_class(MessageClass::Success));
2739 assert!(msg.has_method(BINDING));
2740 assert!(!msg.has_method(Method::new(0x111)));
2741 let software = Software::new("s").unwrap();
2742 msg.add_attribute(&software).unwrap();
2743 msg.add_fingerprint().unwrap();
2744 let bytes = msg.finish();
2745 let new_msg = Message::from_bytes(&bytes).unwrap();
2747 let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2748 assert_eq!(software.software(), "s");
2749 assert_eq!(offset, 20);
2750 let (offset, _new_fingerprint) =
2751 new_msg.raw_attribute_and_offset(Fingerprint::TYPE).unwrap();
2752 assert_eq!(offset, 28);
2753 }
2754
2755 #[test]
2756 fn integrity() {
2757 let _log = crate::tests::test_init_log();
2758 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2759 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2760 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2761 let software = Software::new("s").unwrap();
2762 msg.add_attribute(&software).unwrap();
2763 msg.add_message_integrity(&credentials, algorithm).unwrap();
2764 let bytes = msg.finish();
2765 let new_msg = Message::from_bytes(&bytes).unwrap();
2767 new_msg.validate_integrity(&credentials).unwrap();
2768 let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2769 assert_eq!(software.software(), "s");
2770 assert_eq!(offset, 20);
2771 }
2772 }
2773
2774 #[test]
2775 fn write_into_short_destination() {
2776 let _log = crate::tests::test_init_log();
2777 const LEN: usize = MessageHeader::LENGTH + 8;
2778 let mut data = [0; LEN - 1];
2779 let mut msg = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
2780 let software = Software::new("s").unwrap();
2781 assert!(
2782 matches!(msg.add_attribute(&software), Err(StunWriteError::TooSmall { expected, actual }) if expected == LEN && actual == LEN - 1)
2783 );
2784 }
2785
2786 #[test]
2787 fn integrity_key() {
2788 let _log = crate::tests::test_init_log();
2789 let credentials1 = ShortTermCredentials::new("pass1".to_owned());
2790 let key1 =
2791 MessageIntegrityCredentials::from(credentials1).make_key(IntegrityAlgorithm::Sha1);
2792 let credentials2 = ShortTermCredentials::new("pass2".to_owned());
2793 let key2 =
2794 MessageIntegrityCredentials::from(credentials2).make_key(IntegrityAlgorithm::Sha1);
2795 assert_eq!(key1, key1);
2796 assert_eq!(key2, key2);
2797 assert_ne!(key1, key2);
2798 }
2799
2800 #[test]
2801 fn add_duplicate_integrity() {
2802 let _log = crate::tests::test_init_log();
2803 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2804 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2805 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
2806 .unwrap();
2807 assert!(matches!(
2808 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2809 Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2810 ));
2811 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2812 .unwrap();
2813 assert!(matches!(
2814 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256),
2815 Err(StunWriteError::AttributeExists(
2816 MessageIntegritySha256::TYPE
2817 ))
2818 ));
2819 let software = Software::new("s").unwrap();
2820 assert!(matches!(
2821 msg.add_attribute(&software),
2822 Err(StunWriteError::MessageIntegrityExists)
2823 ));
2824 }
2825
2826 #[test]
2827 fn add_sha1_integrity_after_sha256() {
2828 let _log = crate::tests::test_init_log();
2829 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2830 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2831 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2832 .unwrap();
2833 assert!(matches!(
2834 msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2835 Err(StunWriteError::AttributeExists(
2836 MessageIntegritySha256::TYPE
2837 ))
2838 ));
2839 }
2840
2841 #[test]
2842 fn add_attribute_after_integrity() {
2843 let _log = crate::tests::test_init_log();
2844 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2845 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2846 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2847 msg.add_message_integrity(&credentials, algorithm).unwrap();
2848 let software = Software::new("s").unwrap();
2849 assert!(matches!(
2850 msg.add_attribute(&software),
2851 Err(StunWriteError::MessageIntegrityExists)
2852 ));
2853 }
2854 }
2855
2856 #[test]
2857 fn add_raw_attribute_after_integrity() {
2858 let _log = crate::tests::test_init_log();
2859 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2860 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2861 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2862 msg.add_message_integrity(&credentials, algorithm).unwrap();
2863 let software = Software::new("s").unwrap();
2864 let raw = software.to_raw();
2865 assert!(matches!(
2866 msg.add_attribute(&raw),
2867 Err(StunWriteError::MessageIntegrityExists)
2868 ));
2869 }
2870 }
2871
2872 #[test]
2873 fn add_integrity_after_fingerprint() {
2874 let _log = crate::tests::test_init_log();
2875 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2876 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2877 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2878 msg.add_fingerprint().unwrap();
2879 assert!(matches!(
2880 msg.add_message_integrity(&credentials, algorithm),
2881 Err(StunWriteError::FingerprintExists)
2882 ));
2883 }
2884 }
2885
2886 #[test]
2887 fn duplicate_fingerprint() {
2888 let _log = crate::tests::test_init_log();
2889 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2890 msg.add_fingerprint().unwrap();
2891 assert!(matches!(
2892 msg.add_fingerprint(),
2893 Err(StunWriteError::AttributeExists(Fingerprint::TYPE))
2894 ));
2895 }
2896
2897 #[test]
2898 fn parse_invalid_fingerprint() {
2899 let _log = crate::tests::test_init_log();
2900 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2901 msg.add_fingerprint().unwrap();
2902 let mut bytes = msg.finish();
2903 bytes[24] = 0x80;
2904 bytes[25] = 0x80;
2905 bytes[26] = 0x80;
2906 bytes[27] = 0x80;
2907 assert!(matches!(
2908 Message::from_bytes(&bytes),
2909 Err(StunParseError::FingerprintMismatch)
2910 ));
2911 }
2912
2913 #[test]
2914 fn parse_wrong_magic() {
2915 let _log = crate::tests::test_init_log();
2916 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2917 msg.add_fingerprint().unwrap();
2918 let mut bytes = msg.finish();
2919 bytes[4] = 0x80;
2920 assert!(matches!(
2921 Message::from_bytes(&bytes),
2922 Err(StunParseError::NotStun)
2923 ));
2924 }
2925
2926 #[test]
2927 fn parse_attribute_after_integrity() {
2928 let _log = crate::tests::test_init_log();
2929 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2930 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2931 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2932 msg.add_message_integrity(&credentials, algorithm).unwrap();
2933 let mut bytes = msg.finish();
2934 let software = Software::new("s").unwrap();
2935 let software_bytes = RawAttribute::from(&software).to_bytes();
2936 let software_len = software_bytes.len();
2937 bytes.extend(software_bytes);
2938 bytes[3] += software_len as u8;
2939 let msg = Message::from_bytes(&bytes).unwrap();
2940 assert!(msg.raw_attribute(Software::TYPE).is_none());
2941 }
2942 }
2943
2944 #[test]
2945 fn parse_duplicate_integrity_after_integrity() {
2946 let _log = crate::tests::test_init_log();
2947 for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2948 let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2949 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2950 msg.add_message_integrity(&credentials, algorithm).unwrap();
2951 add_message_integrity_unchecked(
2953 &mut msg,
2954 &credentials.make_key(IntegrityAlgorithm::Sha1),
2955 algorithm,
2956 );
2957 let bytes = msg.finish();
2958 let integrity_type = match algorithm {
2959 IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2960 IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2961 };
2962 let msg = Message::from_bytes(&bytes).unwrap();
2963 msg.nth_raw_attribute(integrity_type, 0).unwrap();
2964 assert!(msg.nth_raw_attribute(integrity_type, 1).is_none());
2965 }
2966 }
2967
2968 #[test]
2969 fn parse_attribute_after_fingerprint() {
2970 let _log = crate::tests::test_init_log();
2971 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2972 msg.add_fingerprint().unwrap();
2973 let mut bytes = msg.finish();
2974 let software = Software::new("s").unwrap();
2975 let software_bytes = RawAttribute::from(&software).to_bytes();
2976 let software_len = software_bytes.len();
2977 bytes.extend(software_bytes);
2978 bytes[3] += software_len as u8;
2979 let msg = Message::from_bytes(&bytes).unwrap();
2980 assert!(msg.raw_attribute(Fingerprint::TYPE).is_some());
2981 assert!(msg.raw_attribute(Software::TYPE).is_none());
2982 }
2983
2984 #[test]
2985 fn parse_duplicate_fingerprint_after_fingerprint() {
2986 let _log = crate::tests::test_init_log();
2987 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2988 msg.add_fingerprint().unwrap();
2989 add_fingerprint_unchecked(&mut msg);
2990 let bytes = msg.finish();
2991 let msg = Message::from_bytes(&bytes).unwrap();
2992 assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 0).is_some());
2993 assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 1).is_none());
2994 }
2995
2996 #[test]
2997 fn add_attribute_after_fingerprint() {
2998 let _log = crate::tests::test_init_log();
2999 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3000 msg.add_fingerprint().unwrap();
3001 let software = Software::new("s").unwrap();
3002 assert!(matches!(
3003 msg.add_attribute(&software),
3004 Err(StunWriteError::FingerprintExists)
3005 ));
3006 }
3007
3008 #[test]
3009 fn add_raw_attribute_after_fingerprint() {
3010 let _log = crate::tests::test_init_log();
3011 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3012 msg.add_fingerprint().unwrap();
3013 let software = Software::new("s").unwrap();
3014 let raw = software.to_raw();
3015 assert!(matches!(
3016 msg.add_attribute(&raw),
3017 Err(StunWriteError::FingerprintExists)
3018 ));
3019 }
3020
3021 #[test]
3022 fn parse_truncated_message_header() {
3023 let _log = crate::tests::test_init_log();
3024 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3025 msg.add_fingerprint().unwrap();
3026 let bytes = msg.finish();
3027 assert!(matches!(
3028 Message::from_bytes(&bytes[..8]),
3029 Err(StunParseError::Truncated {
3030 expected: 20,
3031 actual: 8
3032 })
3033 ));
3034 }
3035
3036 #[test]
3037 fn parse_truncated_message() {
3038 let _log = crate::tests::test_init_log();
3039 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3040 msg.add_fingerprint().unwrap();
3041 let bytes = msg.finish();
3042 assert!(matches!(
3043 Message::from_bytes(&bytes[..24]),
3044 Err(StunParseError::Truncated {
3045 expected: 28,
3046 actual: 24
3047 })
3048 ));
3049 }
3050
3051 #[test]
3052 fn parse_truncated_message_attribute() {
3053 let _log = crate::tests::test_init_log();
3054 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3055 msg.add_fingerprint().unwrap();
3056 let mut bytes = msg.finish();
3057 bytes[3] = 4;
3059 assert!(matches!(
3060 Message::from_bytes(&bytes[..24]),
3061 Err(StunParseError::Truncated {
3062 expected: 28,
3063 actual: 24
3064 })
3065 ));
3066 }
3067
3068 #[test]
3069 fn parse_attribute_extends_past_message_end() {
3070 let _log = crate::tests::test_init_log();
3071 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3072 msg.add_attribute(&Software::new("a").unwrap()).unwrap();
3073 msg[23] += 1;
3074 let mut bytes = msg.finish();
3075 bytes[3] -= 1;
3076 error!("{bytes:x?}");
3077 error!("{:?}", Message::from_bytes(&bytes[..27]));
3078 assert!(matches!(
3079 Message::from_bytes(&bytes[..27]),
3080 Err(StunParseError::Truncated {
3081 expected: 28,
3082 actual: 27
3083 })
3084 ));
3085 }
3086
3087 #[test]
3088 fn valid_attributes() {
3089 let _log = crate::tests::test_init_log();
3090 let mut src = Message::builder_request(BINDING, MessageWriteVec::new());
3091 let username = Username::new("123").unwrap();
3092 src.add_attribute(&username).unwrap();
3093 let nonce = Nonce::new("nonce").unwrap();
3094 src.add_attribute(&nonce).unwrap();
3095 assert!(!src.has_attribute(Fingerprint::TYPE));
3096 assert!(src.has_attribute(Nonce::TYPE));
3097 let src = src.finish();
3098 let src = Message::from_bytes(&src).unwrap();
3099 assert!(!src.has_attribute(Fingerprint::TYPE));
3100 assert!(src.has_attribute(Nonce::TYPE));
3101
3102 let res = Message::check_attribute_types(
3104 &src,
3105 &[Username::TYPE, Nonce::TYPE],
3106 &[Username::TYPE],
3107 MessageWriteVec::new(),
3108 );
3109 assert!(res.is_none());
3110
3111 let res = Message::check_attribute_types(
3113 &src,
3114 &[Username::TYPE, Nonce::TYPE],
3115 &[Fingerprint::TYPE],
3116 MessageWriteVec::new(),
3117 );
3118 assert!(res.is_some());
3119 let res = res.unwrap();
3120 let res = res.finish();
3121 let res = Message::from_bytes(&res).unwrap();
3122 assert!(res.has_class(MessageClass::Error));
3123 assert!(res.has_method(src.method()));
3124 let err = res.attribute::<ErrorCode>().unwrap();
3125 assert_eq!(err.code(), 400);
3126
3127 let res =
3129 Message::check_attribute_types(&src, &[Username::TYPE], &[], MessageWriteVec::new());
3130 assert!(res.is_some());
3131 let res = res.unwrap();
3132 let data = res.finish();
3133 let res = Message::from_bytes(&data).unwrap();
3134 assert!(res.has_class(MessageClass::Error));
3135 assert!(res.has_method(src.method()));
3136 let err = res.attribute::<ErrorCode>().unwrap();
3137 assert_eq!(err.code(), 420);
3138 let unknown = res.attribute::<UnknownAttributes>().unwrap();
3139 assert!(unknown.has_attribute(Nonce::TYPE));
3140 }
3141
3142 #[test]
3143 fn attributes_iter_with_short_data() {
3144 let _log = crate::tests::test_init_log();
3145 assert_eq!(
3146 MessageAttributesIter::new(&[0x0, 0x1, 0x2, 0x3, 0x4]).next(),
3147 None
3148 );
3149 assert_eq!(
3150 MessageAttributesIter::new(&[
3151 0x0, 0x1, 0x2, 0x3, 0x21, 0x12, 0xa4, 0x42, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
3152 0x10, 0x11, 0x12, 0x13, 0x14,
3153 ])
3154 .next(),
3155 None
3156 );
3157 }
3158
3159 #[test]
3160 fn attributes_iter_software_after_fingerprint_ignored() {
3161 let _log = crate::tests::test_init_log();
3162 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3163 msg.add_fingerprint().unwrap();
3164 let mut bytes = msg.finish();
3165 let software = Software::new("s").unwrap();
3166 let software_bytes = RawAttribute::from(&software).to_bytes();
3167 let software_len = software_bytes.len();
3168 bytes.extend(software_bytes);
3169 bytes[3] += software_len as u8;
3170 let mut it = MessageAttributesIter::new(&bytes);
3171 let (_offset, fingerprint) = it.next().unwrap();
3172 assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
3173 assert_eq!(it.next(), None);
3174 }
3175
3176 #[test]
3177 fn attributes_iter_message_integrities_fingerprint() {
3178 let _log = crate::tests::test_init_log();
3179 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3180 let credentials = ShortTermCredentials::new("pass".to_owned());
3181 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
3182 .unwrap();
3183 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
3184 .unwrap();
3185 msg.add_fingerprint().unwrap();
3186 let mut bytes = msg.finish();
3187 let software = Software::new("s").unwrap();
3188 let software_bytes = RawAttribute::from(&software).to_bytes();
3189 let software_len = software_bytes.len();
3190 bytes.extend(software_bytes);
3191 bytes[3] += software_len as u8;
3192 let mut it = MessageAttributesIter::new(&bytes);
3193 assert_eq!(it.next().unwrap().1.get_type(), MessageIntegrity::TYPE);
3194 assert_eq!(
3195 it.next().unwrap().1.get_type(),
3196 MessageIntegritySha256::TYPE
3197 );
3198 assert_eq!(it.next().unwrap().1.get_type(), Fingerprint::TYPE);
3199 assert_eq!(it.next(), None);
3200 }
3201
3202 #[test]
3203 fn message_parse_multiple_integrities_fingerprint() {
3204 let _log = crate::tests::test_init_log();
3205 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3206 let credentials = ShortTermCredentials::new("pass".to_owned());
3207 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
3208 .unwrap();
3209 msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
3210 .unwrap();
3211 msg.add_fingerprint().unwrap();
3212 let key = credentials.make_key();
3213 let bytes = msg.finish();
3214 let msg = Message::from_bytes(&bytes).unwrap();
3215 assert!(msg.has_attribute(MessageIntegrity::TYPE));
3216 assert!(msg.has_attribute(MessageIntegritySha256::TYPE));
3217 assert!(!msg.has_attribute(Software::TYPE));
3218 assert_eq!(
3219 msg.validate_integrity(&credentials.clone().into()).unwrap(),
3220 IntegrityAlgorithm::Sha256
3221 );
3222 assert_eq!(
3223 msg.validate_integrity_with_key(&key).unwrap(),
3224 IntegrityAlgorithm::Sha256
3225 );
3226 }
3227
3228 #[test]
3229 fn validate_integrity_missing_attribute() {
3230 let _log = crate::tests::test_init_log();
3231 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3232 msg.add_fingerprint().unwrap();
3233 let credentials = ShortTermCredentials::new("pass".to_owned());
3234 let key = credentials.make_key();
3235 let bytes = msg.finish();
3236 let msg = Message::from_bytes(&bytes).unwrap();
3237 assert!(matches!(
3238 msg.validate_integrity(&credentials.clone().into()),
3239 Err(ValidateError::Parse(StunParseError::MissingAttribute(
3240 MessageIntegrity::TYPE
3241 )))
3242 ));
3243 assert!(matches!(
3244 msg.validate_integrity_with_key(&key),
3245 Err(ValidateError::Parse(StunParseError::MissingAttribute(
3246 MessageIntegrity::TYPE
3247 )))
3248 ));
3249 }
3250
3251 #[test]
3252 fn attributes_iter_fingerprint_after_fingerprint_ignored() {
3253 let _log = crate::tests::test_init_log();
3254 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3255 msg.add_fingerprint().unwrap();
3256 let mut bytes = msg.finish();
3257 let fingerprint = Fingerprint::new([bytes[bytes.len() - 1].wrapping_sub(1); 4]);
3258 let fingerprint_bytes = RawAttribute::from(&fingerprint).to_bytes();
3259 let fingerprint_len = fingerprint_bytes.len();
3260 bytes.extend(fingerprint_bytes);
3261 bytes[3] += fingerprint_len as u8;
3262 let mut it = MessageAttributesIter::new(&bytes);
3263 let (_offset, fingerprint) = it.next().unwrap();
3264 assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
3265 assert_eq!(it.next(), None);
3266 }
3267
3268 #[test]
3269 fn write_vec_state() {
3270 let _log = crate::tests::test_init_log();
3271 let mut src = Message::builder_request(BINDING, MessageWriteVec::with_capacity(0x10));
3272 assert_eq!(src.len(), 20);
3273 assert_eq!(src[4], 0x21);
3274 let username = Username::new("123").unwrap();
3275 src.add_attribute(&username).unwrap();
3276 let nonce = Nonce::new("nonce").unwrap();
3277 src.add_attribute(&nonce).unwrap();
3278
3279 assert!(src.has_attribute(Username::TYPE));
3280 assert!(src.has_attribute(Nonce::TYPE));
3281 assert_eq!(
3282 src.has_any_attribute(&[Username::TYPE, Nonce::TYPE]),
3283 Some(Username::TYPE)
3284 );
3285 assert_eq!(
3286 src.has_any_attribute(&[Nonce::TYPE, Username::TYPE]),
3287 Some(Username::TYPE)
3288 );
3289 assert!(src.has_class(MessageClass::Request));
3290 assert!(!src.is_response());
3291 assert!(src.has_method(BINDING));
3292 assert!(src.get_type().has_method(BINDING));
3293 assert!(src.get_type().has_class(MessageClass::Request));
3294 assert!(!src.has_method(Method::new(0x111)));
3295 assert!(!src.get_type().has_method(Method::new(0x111)));
3296 assert!(!src.get_type().has_class(MessageClass::Error));
3297 }
3298
3299 #[test]
3300 fn write_mut_slice_success() {
3301 let _log = crate::tests::test_init_log();
3302 let mut data = [0; 64];
3303 let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3304 assert_eq!(src.len(), 20);
3305 assert_eq!(src[4], 0x21);
3306 let username = Username::new("123").unwrap();
3307 src.add_attribute(&username).unwrap();
3308 let nonce = Nonce::new("nonce").unwrap();
3309 src.add_attribute(&nonce).unwrap();
3310 assert!(src.has_attribute(Username::TYPE));
3311 assert_eq!(
3312 src.has_any_attribute(&[Username::TYPE]),
3313 Some(Username::TYPE)
3314 );
3315 assert!(!src.has_attribute(Software::TYPE));
3316 assert_eq!(src.has_any_attribute(&[Realm::TYPE]), None);
3317 assert_eq!(src.mut_data().len(), src.len());
3318 assert_eq!(src.finish(), 40);
3319 let msg = Message::from_bytes(&data[..40]).unwrap();
3320 let u2 = msg.attribute::<Username>().unwrap();
3321 assert_eq!(u2.username(), "123");
3322 let n2 = msg.attribute::<Nonce>().unwrap();
3323 assert_eq!(n2.nonce(), "nonce");
3324 }
3325
3326 #[test]
3327 fn write_mut_slice_too_short() {
3328 let _log = crate::tests::test_init_log();
3329 let mut data = [0; 27];
3330 let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3331 assert!(matches!(
3332 src.add_attribute(&Username::new("123").unwrap()),
3333 Err(StunWriteError::TooSmall {
3334 expected: 28,
3335 actual: 27
3336 })
3337 ));
3338 }
3339
3340 #[test]
3341 #[should_panic(expected = "created from a non-request message")]
3342 fn builder_success_panic() {
3343 let _log = crate::tests::test_init_log();
3344 let msg = Message::builder(
3345 MessageType::from_class_method(MessageClass::Indication, BINDING),
3346 TransactionId::generate(),
3347 MessageWriteVec::new(),
3348 )
3349 .finish();
3350 let msg = Message::from_bytes(&msg).unwrap();
3351 let _builder = Message::builder_success(&msg, MessageWriteVec::new());
3352 }
3353
3354 #[test]
3355 #[should_panic(expected = "created from a non-request message")]
3356 fn builder_error_panic() {
3357 let _log = crate::tests::test_init_log();
3358 let msg = Message::builder(
3359 MessageType::from_class_method(MessageClass::Indication, BINDING),
3360 TransactionId::generate(),
3361 MessageWriteVec::new(),
3362 )
3363 .finish();
3364 let msg = Message::from_bytes(&msg).unwrap();
3365 let _builder = Message::builder_error(&msg, MessageWriteVec::new());
3366 }
3367
3368 #[test]
3369 #[should_panic(expected = "Use add_message_integrity() instead")]
3370 fn builder_add_attribute_integrity_panic() {
3371 let _log = crate::tests::test_init_log();
3372 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3373 let hmac = [2; 20];
3374 let integrity = MessageIntegrity::new(hmac);
3375 msg.add_attribute(&integrity).unwrap();
3376 }
3377
3378 #[test]
3379 #[should_panic(expected = "Use add_message_integrity() instead")]
3380 fn builder_add_raw_attribute_integrity_panic() {
3381 let _log = crate::tests::test_init_log();
3382 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3383 let hmac = [2; 20];
3384 let integrity = MessageIntegrity::new(hmac);
3385 let raw = integrity.to_raw();
3386 msg.add_attribute(&raw).unwrap();
3387 }
3388
3389 #[test]
3390 #[should_panic(expected = "Use add_message_integrity() instead")]
3391 fn builder_add_attribute_integrity_sha256_panic() {
3392 let _log = crate::tests::test_init_log();
3393 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3394 let hmac = [2; 16];
3395 let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3396 msg.add_attribute(&integrity).unwrap();
3397 }
3398
3399 #[test]
3400 #[should_panic(expected = "Use add_message_integrity() instead")]
3401 fn builder_add_raw_attribute_integrity_sha256_panic() {
3402 let _log = crate::tests::test_init_log();
3403 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3404 let hmac = [2; 16];
3405 let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3406 let raw = integrity.to_raw();
3407 msg.add_attribute(&raw).unwrap();
3408 }
3409
3410 #[test]
3411 #[should_panic(expected = "Use add_fingerprint() instead")]
3412 fn builder_add_attribute_fingerprint_panic() {
3413 let _log = crate::tests::test_init_log();
3414 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3415 let fingerprint = [2; 4];
3416 let fingerprint = Fingerprint::new(fingerprint);
3417 msg.add_attribute(&fingerprint).unwrap();
3418 }
3419
3420 #[test]
3421 #[should_panic(expected = "Use add_fingerprint() instead")]
3422 fn builder_add_raw_attribute_fingerprint_panic() {
3423 let _log = crate::tests::test_init_log();
3424 let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3425 let fingerprint = [2; 4];
3426 let fingerprint = Fingerprint::new(fingerprint);
3427 let raw = fingerprint.to_raw();
3428 msg.add_attribute(&raw).unwrap();
3429 }
3430
3431 #[test]
3432 fn rfc5769_vector1() {
3433 let _log = crate::tests::test_init_log();
3434 let data = vec![
3436 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, ];
3464 let msg = Message::from_bytes(&data).unwrap();
3465 assert!(msg.has_class(MessageClass::Request));
3466 assert!(msg.has_method(BINDING));
3467 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3468
3469 let mut builder = Message::builder(
3470 MessageType::from_class_method(MessageClass::Request, BINDING),
3471 msg.transaction_id(),
3472 MessageWriteVec::new(),
3473 );
3474
3475 assert!(msg.has_attribute(Software::TYPE));
3477 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3478 assert!(Software::try_from(&raw).is_ok());
3479 let software = Software::try_from(&raw).unwrap();
3480 assert_eq!(software.software(), "STUN test client");
3481 builder.add_attribute(&software).unwrap();
3482
3483 builder
3485 .add_attribute(&RawAttribute::new(0x24.into(), &[0x6e, 0x00, 0x01, 0xff]))
3486 .unwrap();
3487
3488 builder
3490 .add_attribute(&RawAttribute::new(
3491 0x8029.into(),
3492 &[0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36],
3493 ))
3494 .unwrap();
3495
3496 assert!(msg.has_attribute(Username::TYPE));
3498 let raw = msg.raw_attribute(Username::TYPE).unwrap();
3499 assert!(Username::try_from(&raw).is_ok());
3500 let username = Username::try_from(&raw).unwrap();
3501 assert_eq!(username.username(), "evtj:h6vY");
3502 builder.add_attribute(&username).unwrap();
3503
3504 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3506 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3507 });
3508 assert!(matches!(
3509 msg.validate_integrity(&credentials),
3510 Ok(IntegrityAlgorithm::Sha1)
3511 ));
3512 builder
3513 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3514 .unwrap();
3515
3516 assert!(msg.has_attribute(Fingerprint::TYPE));
3518 builder.add_fingerprint().unwrap();
3519
3520 let mut msg_data = builder.finish();
3522 msg_data[73] = 0x20;
3524 msg_data[74] = 0x20;
3525 msg_data[75] = 0x20;
3526 assert_eq!(msg_data[..80], data[..80]);
3529 }
3530
3531 #[test]
3532 fn rfc5769_vector2() {
3533 let _log = crate::tests::test_init_log();
3534 let data = vec![
3536 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, ];
3557
3558 let msg = Message::from_bytes(&data).unwrap();
3559 assert!(msg.has_class(MessageClass::Success));
3560 assert!(msg.has_method(BINDING));
3561 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3562 let mut builder = Message::builder(
3563 MessageType::from_class_method(MessageClass::Success, BINDING),
3564 msg.transaction_id(),
3565 MessageWriteVec::new(),
3566 );
3567
3568 assert!(msg.has_attribute(Software::TYPE));
3570 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3571 assert!(Software::try_from(&raw).is_ok());
3572 let software = Software::try_from(&raw).unwrap();
3573 assert_eq!(software.software(), "test vector");
3574 builder.add_attribute(&software).unwrap();
3575
3576 assert!(msg.has_attribute(XorMappedAddress::TYPE));
3578 let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3579 assert!(XorMappedAddress::try_from(&raw).is_ok());
3580 let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3581 assert_eq!(
3582 xor_mapped_addres.addr(msg.transaction_id()),
3583 "192.0.2.1:32853".parse().unwrap()
3584 );
3585 builder.add_attribute(&xor_mapped_addres).unwrap();
3586
3587 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3589 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3590 });
3591 let ret = msg.validate_integrity(&credentials);
3592 warn!("{:?}", ret);
3593 assert!(matches!(ret, Ok(IntegrityAlgorithm::Sha1)));
3594 builder
3595 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3596 .unwrap();
3597
3598 assert!(msg.has_attribute(Fingerprint::TYPE));
3600 builder.add_fingerprint().unwrap();
3601
3602 let mut msg_data = builder.finish();
3604 msg_data[35] = 0x20;
3606 assert_eq!(msg_data[..52], data[..52]);
3607 }
3608
3609 #[test]
3610 fn rfc5769_vector3() {
3611 let _log = crate::tests::test_init_log();
3612 let data = vec![
3614 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, ];
3638
3639 let msg = Message::from_bytes(&data).unwrap();
3640 assert!(msg.has_class(MessageClass::Success));
3641 assert!(msg.has_method(BINDING));
3642 assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3643 let mut builder = Message::builder(
3644 MessageType::from_class_method(MessageClass::Success, BINDING),
3645 msg.transaction_id(),
3646 MessageWriteVec::new(),
3647 );
3648
3649 assert!(msg.has_attribute(Software::TYPE));
3651 let raw = msg.raw_attribute(Software::TYPE).unwrap();
3652 assert!(Software::try_from(&raw).is_ok());
3653 let software = Software::try_from(&raw).unwrap();
3654 assert_eq!(software.software(), "test vector");
3655 builder.add_attribute(&software).unwrap();
3656
3657 assert!(msg.has_attribute(XorMappedAddress::TYPE));
3659 let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3660 assert!(XorMappedAddress::try_from(&raw).is_ok());
3661 let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3662 assert_eq!(
3663 xor_mapped_addres.addr(msg.transaction_id()),
3664 "[2001:db8:1234:5678:11:2233:4455:6677]:32853"
3665 .parse()
3666 .unwrap()
3667 );
3668 builder.add_attribute(&xor_mapped_addres).unwrap();
3669
3670 let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3672 password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3673 });
3674 assert!(matches!(
3675 msg.validate_integrity(&credentials),
3676 Ok(IntegrityAlgorithm::Sha1)
3677 ));
3678 builder
3679 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3680 .unwrap();
3681
3682 assert!(msg.has_attribute(Fingerprint::TYPE));
3684 builder.add_fingerprint().unwrap();
3685
3686 let mut msg_data = builder.finish();
3688 msg_data[35] = 0x20;
3690 assert_eq!(msg_data[..64], data[..64]);
3691 }
3692
3693 #[test]
3694 fn rfc5769_vector4() {
3695 let _log = crate::tests::test_init_log();
3696 let data = vec![
3698 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, ];
3728
3729 let msg = Message::from_bytes(&data).unwrap();
3730 assert!(msg.has_class(MessageClass::Request));
3731 assert!(msg.has_method(BINDING));
3732 assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3733 let mut builder = Message::builder(
3734 MessageType::from_class_method(MessageClass::Request, BINDING),
3735 msg.transaction_id(),
3736 MessageWriteVec::new(),
3737 );
3738
3739 let username = stringprep::saslprep("\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}")
3740 .unwrap()
3741 .into_owned();
3742 let password = stringprep::saslprep("The\u{00AD}M\u{00AA}tr\u{2168}")
3743 .unwrap()
3744 .into_owned();
3745 trace!("password: {password:?}");
3746
3747 let long_term = LongTermKeyCredentials {
3748 username,
3749 password,
3750 realm: "example.org".to_owned(),
3751 };
3752 assert!(msg.has_attribute(Username::TYPE));
3754 let raw = msg.raw_attribute(Username::TYPE).unwrap();
3755 assert!(Username::try_from(&raw).is_ok());
3756 let username = Username::try_from(&raw).unwrap();
3757 assert_eq!(username.username(), &long_term.username);
3758 builder.add_attribute(&username).unwrap();
3759
3760 let expected_nonce = "f//499k954d6OL34oL9FSTvy64sA";
3762 assert!(msg.has_attribute(Nonce::TYPE));
3763 let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3764 assert!(Nonce::try_from(&raw).is_ok());
3765 let nonce = Nonce::try_from(&raw).unwrap();
3766 assert_eq!(nonce.nonce(), expected_nonce);
3767 builder.add_attribute(&nonce).unwrap();
3768
3769 assert!(msg.has_attribute(Realm::TYPE));
3771 let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3772 assert!(Realm::try_from(&raw).is_ok());
3773 let realm = Realm::try_from(&raw).unwrap();
3774 assert_eq!(realm.realm(), long_term.realm());
3775 builder.add_attribute(&realm).unwrap();
3776
3777 let credentials = MessageIntegrityCredentials::LongTerm(long_term);
3779 assert!(matches!(
3780 msg.validate_integrity(&credentials),
3781 Ok(IntegrityAlgorithm::Sha1)
3782 ));
3783 builder
3784 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3785 .unwrap();
3786
3787 assert_eq!(builder.finish()[4..], data[4..]);
3788 }
3789
3790 #[test]
3791 fn rfc8489_vector1() {
3792 let _log = crate::tests::test_init_log();
3793 let data = vec![
3796 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, ];
3838 let msg = Message::from_bytes(&data).unwrap();
3839 assert!(msg.has_class(MessageClass::Request));
3840 assert!(msg.has_method(BINDING));
3841 assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3842 let mut builder = Message::builder(
3843 MessageType::from_class_method(MessageClass::Request, BINDING),
3844 msg.transaction_id(),
3845 MessageWriteVec::new(),
3846 );
3847
3848 let opaque = precis_profiles::OpaqueString::new();
3849 let username = opaque
3850 .prepare("\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}")
3851 .unwrap()
3852 .into_owned();
3853 let orig_password = "The\u{00AD}M\u{00AA}tr\u{2168}";
3854 trace!("password: {orig_password:?}");
3855 let sasl_password = stringprep::saslprep(orig_password).unwrap().into_owned();
3878 trace!("password (saslprep): {sasl_password}");
3879
3880 let long_term = LongTermKeyCredentials {
3883 username: username.clone(),
3884 password: sasl_password.clone(),
3885 realm: "example.org".to_owned(),
3886 };
3887 assert!(msg.has_attribute(Userhash::TYPE));
3889 let raw = msg.raw_attribute(Userhash::TYPE).unwrap();
3890 assert!(Userhash::try_from(&raw).is_ok());
3891 let userhash = Userhash::try_from(&raw).unwrap();
3892 builder.add_attribute(&userhash).unwrap();
3893
3894 let expected_nonce = "obMatJos2AAACf//499k954d6OL34oL9FSTvy64sA";
3896 assert!(msg.has_attribute(Nonce::TYPE));
3897 let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3898 assert!(Nonce::try_from(&raw).is_ok());
3899 let nonce = Nonce::try_from(&raw).unwrap();
3900 assert_eq!(nonce.nonce(), expected_nonce);
3901 builder.add_attribute(&nonce).unwrap();
3902
3903 assert!(msg.has_attribute(Realm::TYPE));
3905 let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3906 assert!(Realm::try_from(&raw).is_ok());
3907 let realm = Realm::try_from(&raw).unwrap();
3908 assert_eq!(realm.realm(), long_term.realm);
3909 builder.add_attribute(&realm).unwrap();
3910
3911 assert!(msg.has_attribute(PasswordAlgorithm::TYPE));
3913 let raw = msg.raw_attribute(PasswordAlgorithm::TYPE).unwrap();
3914 assert!(PasswordAlgorithm::try_from(&raw).is_ok());
3915 let algo = PasswordAlgorithm::try_from(&raw).unwrap();
3916 assert_eq!(algo.algorithm(), PasswordAlgorithmValue::SHA256);
3917 builder.add_attribute(&algo).unwrap();
3918
3919 trace!("long term: {long_term:?}");
3940 let credentials = MessageIntegrityCredentials::LongTerm(long_term);
3941 assert!(matches!(
3942 msg.validate_integrity(&credentials),
3943 Ok(IntegrityAlgorithm::Sha256)
3944 ));
3945 builder
3946 .add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
3947 .unwrap();
3948
3949 assert_eq!(builder.finish()[4..], data[4..]);
3950 }
3951}