Skip to main content

stun_types/
message.rs

1// Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8//
9// SPDX-License-Identifier: MIT OR Apache-2.0
10
11//! STUN Messages
12//!
13//! Provides types for generating, parsing, and manipulating STUN messages as specified in one of
14//! [RFC8489], [RFC5389], or [RFC3489].
15//!
16//! Message parsing is zerocopy by default through the [`RawAttribute`] struct. Converting to a
17//! concrete attribute implementation (e.g. [`Software`]) may incur a
18//! copy depending on the attribute implementation.
19//!
20//! The destination for a written Message is completely customizable through the [`MessageWrite`]
21//! trait. It is therefore possible to write directly into network provided buffers for increased
22//! performance and throughput.
23//!
24//! [RFC8489]: https://tools.ietf.org/html/rfc8489
25//! [RFC5389]: https://tools.ietf.org/html/rfc5389
26//! [RFC3489]: https://tools.ietf.org/html/rfc3489
27//!
28//! ## Examples
29//!
30//! ### Parse a STUN [`Message`]
31//!
32//! ```
33//! use stun_types::prelude::*;
34//! use stun_types::attribute::{RawAttribute, PasswordAlgorithm, PasswordAlgorithmValue};
35//! use stun_types::message::{Message, MessageType, MessageClass, BINDING};
36//!
37//! let msg_data = [
38//!     0x00, 0x01, 0x00, 0x08, // method, class and length
39//!     0x21, 0x12, 0xA4, 0x42, // Fixed STUN magic bytes
40//!     0x00, 0x00, 0x00, 0x00, // \
41//!     0x00, 0x00, 0x00, 0x00, // } transaction ID
42//!     0x00, 0x00, 0x73, 0x92, // /
43//!     0x00, 0x1D, 0x00, 0x04, // PasswordAlgorithm attribute header (type and length)
44//!     0x00, 0x02, 0x00, 0x00  // PasswordAlgorithm attribute value
45//! ];
46//! let msg = Message::from_bytes(&msg_data).unwrap();
47//!
48//! // the various parts of a message can be retreived
49//! assert_eq!(msg.get_type(), MessageType::from_class_method(MessageClass::Request, BINDING));
50//! assert_eq!(msg.transaction_id(), 0x7392.into());
51//!
52//! // Attributes can be retrieved as raw values.
53//! let msg_attr = msg.raw_attribute(0x1D.into()).unwrap();
54//! let attr = RawAttribute::new(0x1D.into(), &[0, 2, 0, 0]);
55//! assert_eq!(msg_attr, attr);
56//!
57//! // Or as typed values
58//! let attr = msg.attribute::<PasswordAlgorithm>().unwrap();
59//! assert_eq!(attr.algorithm(), PasswordAlgorithmValue::SHA256);
60//! ```
61//!
62//! ### Generating a [`Message`]
63//!
64//! ```
65//! use stun_types::prelude::*;
66//! use stun_types::attribute::Software;
67//! use stun_types::message::{Message, MessageWriteVec, BINDING};
68//!
69//! // Automatically generates a transaction ID.
70//! let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
71//!
72//! let software_name = "stun-types";
73//! let software = Software::new(software_name).unwrap();
74//! assert_eq!(software.software(), software_name);
75//! msg.add_attribute(&software).unwrap();
76//!
77//! let attribute_data = [
78//!     0x80, 0x22, 0x00, 0x0a, // attribute type (0x8022) and length (0x000a)
79//!     0x73, 0x74, 0x75, 0x6E, // s t u n
80//!     0x2D, 0x74, 0x79, 0x70, // - t y p
81//!     0x65, 0x73, 0x00, 0x00  // e s
82//! ];
83//!
84//! let msg_data = msg.finish();
85//! // ignores the randomly generated transaction id
86//! assert_eq!(msg_data[20..], attribute_data);
87//! ```
88
89#[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;
96use core::num::NonZeroUsize;
97#[cfg(feature = "std")]
98use std::sync::{Mutex, OnceLock};
99
100use byteorder::{BigEndian, ByteOrder};
101
102use crate::attribute::*;
103
104use tracing::{debug, trace, warn};
105
106use hmac::digest::core_api::CoreWrapper;
107use hmac::digest::CtOutput;
108use hmac::HmacCore;
109
110/// The value of the magic cookie (in network byte order) as specified in RFC5389, and RFC8489.
111pub const MAGIC_COOKIE: u32 = 0x2112A442;
112
113/// The method in a STUN [`Message`].
114#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
115pub struct Method(u16);
116
117impl core::fmt::Display for Method {
118    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119        write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
120    }
121}
122
123#[cfg(feature = "std")]
124static METHOD_NAME_MAP: OnceLock<Mutex<BTreeMap<Method, &'static str>>> = OnceLock::new();
125
126impl Method {
127    /// Add the name for a particular [`Method`] for formatting purposes.
128    #[cfg(feature = "std")]
129    pub fn add_name(self, name: &'static str) {
130        let mut mnames = METHOD_NAME_MAP
131            .get_or_init(Default::default)
132            .lock()
133            .unwrap();
134        mnames.insert(self, name);
135    }
136
137    /// Create a new [`Method`] from an existing value.
138    ///
139    /// Note: the value passed in is not encoded as in a stun message.
140    ///
141    /// Panics if the value is out of range (>= 0xf000).
142    ///
143    /// # Examples
144    /// ```
145    /// # use stun_types::message::Method;
146    /// assert_eq!(Method::new(0x123).value(), 0x123);
147    /// ```
148    pub const fn new(val: u16) -> Self {
149        if val >= 0xf000 {
150            panic!("Method value is out of range!");
151        }
152        Self(val)
153    }
154
155    /// Return the integer value of this [`Method`].
156    ///
157    /// Note: the value returned is not encoded as in a stun message.
158    ///
159    /// # Examples
160    /// ```
161    /// # use stun_types::message::Method;
162    /// assert_eq!(Method::new(0x123).value(), 0x123);
163    /// ```
164    pub fn value(&self) -> u16 {
165        self.0
166    }
167
168    /// Returns a human readable name of this `Method` or "unknown".
169    ///
170    /// # Examples
171    /// ```
172    /// # use stun_types::attribute::*;
173    /// assert_eq!(XorMappedAddress::TYPE.name(), "XOR-MAPPED-ADDRESS");
174    /// ```
175    pub fn name(self) -> &'static str {
176        match self {
177            BINDING => "BINDING",
178            _ => {
179                #[cfg(feature = "std")]
180                {
181                    let mnames = METHOD_NAME_MAP
182                        .get_or_init(Default::default)
183                        .lock()
184                        .unwrap();
185                    if let Some(name) = mnames.get(&self) {
186                        return name;
187                    }
188                }
189                "unknown"
190            }
191        }
192    }
193}
194
195/// The value of the binding message type.  Can be used in either a request or an indication
196/// message.
197pub const BINDING: Method = Method::new(0x0001);
198
199/// Possible errors when parsing a STUN message.
200#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)]
201#[non_exhaustive]
202pub enum StunParseError {
203    /// Not a STUN message..
204    #[error("The provided data is not a STUN message")]
205    NotStun,
206    /// The message has been truncated.
207    #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
208    Truncated {
209        /// The expeced number of bytes.
210        expected: usize,
211        /// The encountered number of bytes.
212        actual: usize,
213    },
214    /// The message has been truncated.
215    #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
216    TooLarge {
217        /// The expeced number of bytes.
218        expected: usize,
219        /// The encountered number of bytes.
220        actual: usize,
221    },
222    /// An attribute was not found in the message.
223    #[error("Missing attribute {}", .0)]
224    MissingAttribute(AttributeType),
225    /// An attribute was found after the message integrity attribute.
226    #[error("An attribute {} was encountered after a message integrity attribute", .0)]
227    AttributeAfterIntegrity(AttributeType),
228    /// An attribute was found after the message integrity attribute.
229    #[error("An attribute {} was encountered after a fingerprint attribute", .0)]
230    AttributeAfterFingerprint(AttributeType),
231    /// Fingerprint does not match the data.
232    #[error("Fingerprint does not match")]
233    FingerprintMismatch,
234    /// The provided data does not match the message.
235    #[error("The provided data does not match the message")]
236    DataMismatch,
237    /// The attribute contains invalid data.
238    #[error("The attribute contains invalid data")]
239    InvalidAttributeData,
240    /// The attribute does not parse this data.
241    #[error("Cannot parse with this attribute")]
242    WrongAttributeImplementation,
243}
244
245/// Errors produced when writing a STUN message.
246#[derive(Debug, thiserror::Error)]
247#[non_exhaustive]
248pub enum StunWriteError {
249    /// The message already has this attribute.
250    #[error("The attribute already exists in the message")]
251    AttributeExists(AttributeType),
252    /// The fingerprint attribute already exists. Cannot write any further attributes.
253    #[error("The message already contains a fingerprint attribute")]
254    FingerprintExists,
255    /// A message integrity attribute already exists. Cannot write any further attributes.
256    #[error("The message already contains a message intregrity attribute")]
257    MessageIntegrityExists,
258    /// The message has been truncated.
259    #[error("Too many bytes for this data, expected {}, actual {}", .expected, .actual)]
260    TooLarge {
261        /// The expeced number of bytes.
262        expected: usize,
263        /// The encountered number of bytes.
264        actual: usize,
265    },
266    /// The message has been truncated.
267    #[error("Not enough data available to parse the packet, expected {}, actual {}", .expected, .actual)]
268    TooSmall {
269        /// The expected number of bytes.
270        expected: usize,
271        /// The encountered number of bytes.
272        actual: usize,
273    },
274    /// Failed to compute integrity.
275    #[error("Failed to compute integrity")]
276    IntegrityFailed,
277    /// Out of range input provided.
278    #[error("Out of range input provided")]
279    OutOfRange {
280        /// The value provided.
281        value: usize,
282        /// The minimum allowed value.
283        min: usize,
284        /// The maximum allowed value.
285        max: usize,
286    },
287}
288
289/// Errors produced when validating a STUN message.
290#[derive(Debug, thiserror::Error, Copy, Clone)]
291pub enum ValidateError {
292    /// The message failed to parse the relevant integrity attributes.
293    #[error("The message failed to parse the relevant integrity attributes")]
294    Parse(StunParseError),
295    /// The message failed integrity checks.
296    #[error("The message failed integrity checks")]
297    IntegrityFailed,
298}
299
300impl From<StunParseError> for ValidateError {
301    fn from(value: StunParseError) -> Self {
302        Self::Parse(value)
303    }
304}
305
306/// Structure for holding the required credentials for long-term STUN credentials.
307#[derive(Debug, Clone, PartialEq, Eq)]
308#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
309pub struct LongTermCredentials {
310    username: String,
311    password: String,
312}
313
314impl LongTermCredentials {
315    /// Create a new set of [`LongTermCredentials`].
316    ///
317    /// # Examples
318    ///
319    /// ```
320    /// # use stun_types::message::LongTermCredentials;
321    /// let credentials = LongTermCredentials::new(
322    ///     "user".to_string(),
323    ///     "pass".to_string(),
324    /// );
325    /// assert_eq!(credentials.username(), "user");
326    /// assert_eq!(credentials.password(), "pass");
327    /// ```
328    pub fn new(username: String, password: String) -> Self {
329        Self { username, password }
330    }
331
332    /// The configured username
333    pub fn username(&self) -> &str {
334        &self.username
335    }
336
337    /// The configured password
338    pub fn password(&self) -> &str {
339        &self.password
340    }
341
342    /// Construct credentials suitable for signing STUN messages.
343    pub fn to_key(&self, realm: String) -> LongTermKeyCredentials {
344        LongTermKeyCredentials {
345            username: self.username.clone(),
346            password: self.password.clone(),
347            realm,
348        }
349    }
350}
351
352/// Structure for holding the required long term credentials for signing STUN messages.
353#[derive(Debug, Clone, PartialEq, Eq)]
354#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
355pub struct LongTermKeyCredentials {
356    username: String,
357    password: String,
358    realm: String,
359}
360
361impl LongTermKeyCredentials {
362    /// Create a new set of [`LongTermCredentials`].
363    ///
364    /// # Examples
365    ///
366    /// ```
367    /// # use stun_types::message::LongTermKeyCredentials;
368    /// let credentials = LongTermKeyCredentials::new(
369    ///     "user".to_string(),
370    ///     "pass".to_string(),
371    ///     "realm".to_string(),
372    /// );
373    /// assert_eq!(credentials.username(), "user");
374    /// assert_eq!(credentials.password(), "pass");
375    /// assert_eq!(credentials.realm(), "realm");
376    /// ```
377    pub fn new(username: String, password: String, realm: String) -> Self {
378        Self {
379            username,
380            password,
381            realm,
382        }
383    }
384
385    /// The configured username.
386    pub fn username(&self) -> &str {
387        &self.username
388    }
389
390    /// The configured password.
391    pub fn password(&self) -> &str {
392        &self.password
393    }
394
395    /// The configured realm.
396    pub fn realm(&self) -> &str {
397        &self.realm
398    }
399
400    /// Compute a key for caching purposes.
401    pub fn make_key(&self, algorithm: IntegrityAlgorithm) -> IntegrityKey {
402        match algorithm {
403            IntegrityAlgorithm::Sha1 => {
404                use md5::{Digest, Md5};
405                let mut digest = Md5::new();
406                digest.update(self.username.as_bytes());
407                digest.update(":".as_bytes());
408                digest.update(self.realm.as_bytes());
409                digest.update(":".as_bytes());
410                digest.update(self.password.as_bytes());
411                IntegrityKey::new_with_algo(IntegrityAlgorithm::Sha1, digest.finalize().to_vec())
412            }
413            IntegrityAlgorithm::Sha256 => {
414                use sha2::{Digest, Sha256};
415                let mut digest = Sha256::new();
416                digest.update(self.username.as_bytes());
417                digest.update(":".as_bytes());
418                digest.update(self.realm.as_bytes());
419                digest.update(":".as_bytes());
420                digest.update(self.password.as_bytes());
421                IntegrityKey::new_with_algo(IntegrityAlgorithm::Sha256, digest.finalize().to_vec())
422            }
423        }
424    }
425}
426
427/// Structure for holding the required credentials for handling short-term STUN credentials.
428#[derive(Debug, Clone, PartialEq, Eq)]
429#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
430pub struct ShortTermCredentials {
431    password: String,
432}
433
434impl ShortTermCredentials {
435    /// Create a new set of [`ShortTermCredentials`].
436    ///
437    /// # Examples
438    ///
439    /// ```
440    /// # use stun_types::message::ShortTermCredentials;
441    /// let credentials = ShortTermCredentials::new("password".to_string());
442    /// assert_eq!(credentials.password(), "password");
443    /// ```
444    pub fn new(password: String) -> Self {
445        Self { password }
446    }
447
448    /// The configured password.
449    pub fn password(&self) -> &str {
450        &self.password
451    }
452
453    /// Compute a key for caching purposes.
454    pub fn make_key(&self) -> IntegrityKey {
455        IntegrityKey::new(self.password.as_bytes().to_vec())
456    }
457}
458
459/// Enum for holding the credentials used to sign or verify a [`Message`]
460///
461/// This can either be a set of [`ShortTermCredentials`] or [`LongTermCredentials`]`
462#[derive(Debug, Clone, PartialEq, Eq)]
463#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
464pub enum MessageIntegrityCredentials {
465    /// Short term integrity credentials.
466    ShortTerm(ShortTermCredentials),
467    /// Long term integrity credentials.
468    LongTerm(LongTermKeyCredentials),
469}
470
471impl From<LongTermKeyCredentials> for MessageIntegrityCredentials {
472    fn from(value: LongTermKeyCredentials) -> Self {
473        MessageIntegrityCredentials::LongTerm(value)
474    }
475}
476
477impl From<ShortTermCredentials> for MessageIntegrityCredentials {
478    fn from(value: ShortTermCredentials) -> Self {
479        MessageIntegrityCredentials::ShortTerm(value)
480    }
481}
482
483impl MessageIntegrityCredentials {
484    /// Compute a key for caching purposes.
485    pub fn make_key(&self, algorithm: IntegrityAlgorithm) -> IntegrityKey {
486        match self {
487            MessageIntegrityCredentials::ShortTerm(short) => short.make_key(),
488            MessageIntegrityCredentials::LongTerm(long) => long.make_key(algorithm),
489        }
490    }
491}
492
493type HmacSha1 = hmac::Hmac<sha1::Sha1>;
494type HmacSha256 = hmac::Hmac<sha2::Sha256>;
495
496/// A cached key for a particular set of credentials.
497#[derive(Debug, Clone)]
498pub struct IntegrityKey {
499    key_algorithm: Option<IntegrityAlgorithm>,
500    bytes: Vec<u8>,
501    #[cfg(feature = "std")]
502    sha1: Arc<Mutex<Option<HmacSha1>>>,
503    #[cfg(feature = "std")]
504    sha256: Arc<Mutex<Option<HmacSha256>>>,
505}
506
507impl PartialEq<IntegrityKey> for IntegrityKey {
508    fn eq(&self, other: &Self) -> bool {
509        self.bytes == other.bytes
510    }
511}
512
513impl Eq for IntegrityKey {}
514
515impl IntegrityKey {
516    fn new(bytes: Vec<u8>) -> Self {
517        Self {
518            key_algorithm: None,
519            bytes,
520            #[cfg(feature = "std")]
521            sha1: Default::default(),
522            #[cfg(feature = "std")]
523            sha256: Default::default(),
524        }
525    }
526    fn new_with_algo(key_algorithm: IntegrityAlgorithm, bytes: Vec<u8>) -> Self {
527        let mut ret = Self::new(bytes);
528        ret.key_algorithm = Some(key_algorithm);
529        ret
530    }
531    pub(crate) fn as_bytes(&self) -> &[u8] {
532        &self.bytes
533    }
534
535    pub(crate) fn verify_sha1(&self, data: &[&[u8]], expected: &[u8]) -> bool {
536        if self
537            .key_algorithm
538            .is_some_and(|algo| algo != IntegrityAlgorithm::Sha1)
539        {
540            return false;
541        }
542        use hmac::digest::Output;
543        let computed = self.compute_sha1(data);
544        // FIXME: ignore deprecation due to needing to update to generic-array 1.x
545        #[allow(deprecated)]
546        {
547            computed == Output::<sha1::Sha1Core>::from_slice(expected).into()
548        }
549    }
550
551    pub(crate) fn compute_sha1(
552        &self,
553        data: &[&[u8]],
554    ) -> CtOutput<CoreWrapper<HmacCore<CoreWrapper<sha1::Sha1Core>>>> {
555        use hmac::Mac;
556        #[cfg(feature = "std")]
557        let mut sha1 = self.sha1.lock().unwrap();
558        #[cfg(feature = "std")]
559        let hmac = sha1.get_or_insert_with(|| HmacSha1::new_from_slice(self.as_bytes()).unwrap());
560        #[cfg(not(feature = "std"))]
561        let mut hmac = HmacSha1::new_from_slice(self.as_bytes()).unwrap();
562
563        for data in data {
564            hmac.update(data);
565        }
566        #[cfg(feature = "std")]
567        let ret = hmac.finalize_reset();
568        #[cfg(not(feature = "std"))]
569        let ret = hmac.finalize();
570        ret
571    }
572
573    pub(crate) fn verify_sha256(&self, data: &[&[u8]], expected: &[u8]) -> bool {
574        use subtle::ConstantTimeEq;
575        if self
576            .key_algorithm
577            .is_some_and(|algo| algo != IntegrityAlgorithm::Sha256)
578        {
579            return false;
580        }
581        if expected.is_empty() {
582            return false;
583        }
584        let computed = self.compute_sha256(data);
585        if computed.len() < expected.len() {
586            return false;
587        }
588        computed[..expected.len()].ct_eq(expected).into()
589    }
590
591    pub(crate) fn compute_sha256(&self, data: &[&[u8]]) -> [u8; 32] {
592        trace!("computing sha256 using {data:?}");
593        use hmac::Mac;
594        #[cfg(feature = "std")]
595        let mut sha256 = self.sha256.lock().unwrap();
596        #[cfg(feature = "std")]
597        let hmac =
598            sha256.get_or_insert_with(|| HmacSha256::new_from_slice(self.as_bytes()).unwrap());
599        #[cfg(not(feature = "std"))]
600        let mut hmac = HmacSha256::new_from_slice(self.as_bytes()).unwrap();
601
602        for data in data {
603            hmac.update(data);
604        }
605        #[cfg(feature = "std")]
606        let ret = hmac.finalize_reset();
607        #[cfg(not(feature = "std"))]
608        let ret = hmac.finalize();
609        ret.into_bytes().into()
610    }
611}
612
613/// The class of a [`Message`].
614///
615/// There are four classes of [`Message`]s within the STUN protocol:
616///
617///  - [Request][`MessageClass::Request`] indicates that a request is being made and a
618///    response is expected.
619///  - An [Indication][`MessageClass::Indication`] is a fire and forget [`Message`] where
620///    no response is required or expected.
621///  - [Success][`MessageClass::Success`] indicates that a [Request][`MessageClass::Request`]
622///    was successfully handled and the
623///  - [Error][`MessageClass::Error`] class indicates that an error was produced.
624#[derive(Copy, Clone, Debug, PartialEq, Eq)]
625pub enum MessageClass {
626    /// A request that is expecting a response of either Success, or Error.
627    Request,
628    /// A request that does not expect a response.
629    Indication,
630    /// A success response to a previous Request.
631    Success,
632    /// An error response to a previous Request.
633    Error,
634}
635
636impl MessageClass {
637    /// Returns whether this [`MessageClass`] is of a response type.  i.e. is either
638    /// [`MessageClass::Success`] or [`MessageClass::Error`].
639    pub fn is_response(self) -> bool {
640        matches!(self, MessageClass::Success | MessageClass::Error)
641    }
642
643    fn to_bits(self) -> u16 {
644        match self {
645            MessageClass::Request => 0x000,
646            MessageClass::Indication => 0x010,
647            MessageClass::Success => 0x100,
648            MessageClass::Error => 0x110,
649        }
650    }
651}
652
653/// The type of a [`Message`].  A combination of a [`MessageClass`] and a STUN method.
654#[derive(Copy, Clone, Debug, PartialEq, Eq)]
655pub struct MessageType(u16);
656
657impl core::fmt::Display for MessageType {
658    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
659        write!(
660            f,
661            "MessageType(class: {:?}, method: {}",
662            self.class(),
663            self.method(),
664        )
665    }
666}
667
668impl MessageType {
669    /// Create a new [`MessageType`] from the provided [`MessageClass`] and method.
670    ///
671    /// # Examples
672    ///
673    /// ```
674    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
675    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
676    /// assert_eq!(mtype.has_class(MessageClass::Indication), true);
677    /// assert_eq!(mtype.has_method(BINDING), true);
678    /// ```
679    pub fn from_class_method(class: MessageClass, method: Method) -> Self {
680        let class_bits = MessageClass::to_bits(class);
681        let method = method.value();
682        let method_bits = method & 0xf | (method & 0x70) << 1 | (method & 0xf80) << 2;
683        // trace!("MessageType from class {:?} and method {:?} into {:?}", class, method,
684        //     class_bits | method_bits);
685        Self(class_bits | method_bits)
686    }
687
688    /// Retrieves the class of a [`MessageType`].
689    ///
690    /// # Examples
691    ///
692    /// ```
693    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
694    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
695    /// assert_eq!(mtype.class(), MessageClass::Indication);
696    /// ```
697    pub fn class(self) -> MessageClass {
698        let class = (self.0 & 0x10) >> 4 | (self.0 & 0x100) >> 7;
699        match class {
700            0x0 => MessageClass::Request,
701            0x1 => MessageClass::Indication,
702            0x2 => MessageClass::Success,
703            0x3 => MessageClass::Error,
704            _ => unreachable!(),
705        }
706    }
707
708    /// Returns whether class of a [`MessageType`] is equal to the provided [`MessageClass`].
709    ///
710    /// # Examples
711    ///
712    /// ```
713    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
714    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
715    /// assert!(mtype.has_class(MessageClass::Indication));
716    /// ```
717    pub fn has_class(self, cls: MessageClass) -> bool {
718        self.class() == cls
719    }
720
721    /// Returns whether the class of a [`MessageType`] indicates a response [`Message`].
722    ///
723    /// # Examples
724    ///
725    /// ```
726    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
727    /// assert_eq!(MessageType::from_class_method(MessageClass::Indication, BINDING)
728    ///     .is_response(), false);
729    /// assert_eq!(MessageType::from_class_method(MessageClass::Request, BINDING)
730    ///     .is_response(), false);
731    /// assert_eq!(MessageType::from_class_method(MessageClass::Success, BINDING)
732    ///     .is_response(), true);
733    /// assert_eq!(MessageType::from_class_method(MessageClass::Error, BINDING)
734    ///     .is_response(), true);
735    /// ```
736    pub fn is_response(self) -> bool {
737        self.class().is_response()
738    }
739
740    /// Returns the method of a [`MessageType`].
741    ///
742    /// # Examples
743    ///
744    /// ```
745    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
746    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
747    /// assert_eq!(mtype.method(), BINDING);
748    /// ```
749    pub fn method(self) -> Method {
750        Method::new(self.0 & 0xf | (self.0 & 0xe0) >> 1 | (self.0 & 0x3e00) >> 2)
751    }
752
753    /// Returns whether the method of a [`MessageType`] is equal to the provided value.
754    ///
755    /// # Examples
756    ///
757    /// ```
758    /// # use stun_types::message::{MessageType, MessageClass, BINDING};
759    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
760    /// assert_eq!(mtype.has_method(BINDING), true);
761    /// ```
762    pub fn has_method(self, method: Method) -> bool {
763        self.method() == method
764    }
765
766    /// Convert a [`MessageType`] to network bytes.
767    pub fn write_into(&self, dest: &mut [u8]) {
768        BigEndian::write_u16(dest, self.0);
769    }
770
771    /// Convert a [`MessageType`] to network bytes.
772    pub fn to_bytes(self) -> Vec<u8> {
773        let mut ret = vec![0; 2];
774        BigEndian::write_u16(&mut ret[0..2], self.0);
775        ret
776    }
777
778    /// Convert a set of network bytes into a [`MessageType`] or return an error
779    pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
780        let data = BigEndian::read_u16(data);
781        if data & 0xc000 != 0x0 {
782            /* not a stun packet */
783            return Err(StunParseError::NotStun);
784        }
785        Ok(Self(data))
786    }
787}
788impl TryFrom<&[u8]> for MessageType {
789    type Error = StunParseError;
790
791    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
792        MessageType::from_bytes(value)
793    }
794}
795
796/// A unique transaction identifier for each message and it's (possible) response.
797#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
798pub struct TransactionId {
799    id: u128,
800}
801
802impl TransactionId {
803    /// Generate a new STUN transaction identifier.
804    pub fn generate() -> TransactionId {
805        #[cfg(not(feature = "std"))]
806        {
807            use rand::TryRngCore;
808            let mut dest = [0; 16];
809            rand::rngs::OsRng
810                .try_fill_bytes(&mut dest)
811                .expect("Cannot generate random data");
812            u128::from_be_bytes(dest).into()
813        }
814        #[cfg(feature = "std")]
815        {
816            use rand::Rng;
817            let mut rng = rand::rng();
818            rng.random::<u128>().into()
819        }
820    }
821}
822
823impl From<u128> for TransactionId {
824    fn from(id: u128) -> Self {
825        Self {
826            id: id & 0xffff_ffff_ffff_ffff_ffff_ffff,
827        }
828    }
829}
830impl From<TransactionId> for u128 {
831    fn from(id: TransactionId) -> Self {
832        id.id
833    }
834}
835impl core::fmt::Display for TransactionId {
836    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
837        write!(f, "{:#x}", self.id)
838    }
839}
840
841/// The fixed length header of a STUN message.
842///
843/// Allows reading the message header for a quick check if this message is a valid STUN message.
844/// Can also be used to expose the length of the complete message without needing to receive
845/// the entire message.
846#[derive(Debug)]
847pub struct MessageHeader {
848    mtype: MessageType,
849    transaction_id: TransactionId,
850    length: u16,
851}
852
853impl MessageHeader {
854    /// The length of the STUN message header.
855    pub const LENGTH: usize = 20;
856
857    /// Deserialize a `MessageHeader`.
858    ///
859    /// If less than [`MessageHeader::LENGTH`] bytes are provided, the bytes that are available
860    /// are still validated.  [`StunParseError::NotStun`] is returned as soon as the data cannot be
861    /// the start of a STUN message, and [`StunParseError::Truncated`] is only returned when the
862    /// data may be the start of a STUN message.  This allows a STUN message that is received in
863    /// multiple pieces (e.g. over TCP) to be rejected as early as possible.
864    ///
865    /// # Examples
866    ///
867    /// ```
868    /// # use stun_types::message::{MessageHeader, MessageType, MessageClass, BINDING, StunParseError};
869    /// let msg_data = [0, 1, 0, 8, 33, 18, 164, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 232];
870    /// let message = MessageHeader::from_bytes(&msg_data).unwrap();
871    /// assert_eq!(message.get_type(), MessageType::from_class_method(MessageClass::Request, BINDING));
872    /// assert_eq!(message.transaction_id(), 1000.into());
873    /// assert_eq!(message.data_length(), 8);
874    ///
875    /// // The start of a STUN message header.
876    /// assert!(matches!(
877    ///     MessageHeader::from_bytes(&msg_data[..6]),
878    ///     Err(StunParseError::Truncated { expected: 20, actual: 6 })
879    /// ));
880    /// // Not the start of a STUN message header, the magic cookie does not match.
881    /// assert!(matches!(
882    ///     MessageHeader::from_bytes(&[0, 1, 0, 8, 33, 0]),
883    ///     Err(StunParseError::NotStun)
884    /// ));
885    /// ```
886    pub fn from_bytes(data: &[u8]) -> Result<Self, StunParseError> {
887        if data.len() < 20 {
888            // validate the bytes that are available
889            if data.first().is_some_and(|&b| b & 0xc0 != 0) {
890                /* not a stun packet */
891                return Err(StunParseError::NotStun);
892            }
893            let cookie = &data[data.len().min(4)..data.len().min(8)];
894            let magic = MAGIC_COOKIE.to_be_bytes();
895            if cookie != &magic[..cookie.len()] {
896                debug!(
897                    "malformed cookie constant {:?} != stored data {:?}",
898                    &magic[..cookie.len()],
899                    cookie
900                );
901                return Err(StunParseError::NotStun);
902            }
903            return Err(StunParseError::Truncated {
904                expected: 20,
905                actual: data.len(),
906            });
907        }
908        let mtype = MessageType::from_bytes(data)?;
909        let mlength = BigEndian::read_u16(&data[2..]);
910        let tid = BigEndian::read_u128(&data[4..]);
911        let cookie = (tid >> 96) as u32;
912        if cookie != MAGIC_COOKIE {
913            debug!(
914                "malformed cookie constant {:?} != stored data {:?}",
915                MAGIC_COOKIE, cookie
916            );
917            return Err(StunParseError::NotStun);
918        }
919
920        Ok(Self {
921            mtype,
922            transaction_id: tid.into(),
923            length: mlength,
924        })
925    }
926
927    /// The number of bytes of content in this [`MessageHeader`]. Adding both `data_length()`
928    /// and [`MessageHeader::LENGTH`] will result in the size of the complete STUN message.
929    pub fn data_length(&self) -> u16 {
930        self.length
931    }
932
933    /// The [`TransactionId`] of this [`MessageHeader`].
934    pub fn transaction_id(&self) -> TransactionId {
935        self.transaction_id
936    }
937
938    /// The [`MessageType`] of this [`MessageHeader`].
939    pub fn get_type(&self) -> MessageType {
940        self.mtype
941    }
942
943    fn new(mtype: MessageType, transaction_id: TransactionId, length: u16) -> Self {
944        Self {
945            mtype,
946            transaction_id,
947            length,
948        }
949    }
950
951    fn write_into(&self, dest: &mut [u8]) {
952        self.mtype.write_into(&mut dest[..2]);
953        let transaction: u128 = self.transaction_id.into();
954        let tid = (MAGIC_COOKIE as u128) << 96 | transaction & 0xffff_ffff_ffff_ffff_ffff_ffff;
955        BigEndian::write_u128(&mut dest[4..20], tid);
956        BigEndian::write_u16(&mut dest[2..4], self.length);
957    }
958}
959
960/// The structure that encapsulates the entirety of a STUN message.
961///
962/// Contains the [`MessageType`], a transaction ID, and a list of STUN
963/// [`Attribute`].
964#[derive(Debug, Clone, Copy)]
965pub struct Message<'a> {
966    data: &'a [u8],
967    integrity_offset: Option<NonZeroUsize>,
968}
969
970impl core::fmt::Display for Message<'_> {
971    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
972        write!(
973            f,
974            "Message(class: {:?}, method: {}, transaction: {}, attributes: ",
975            self.get_type().class(),
976            self.get_type().method(),
977            self.transaction_id()
978        )?;
979        let iter = self.iter_attributes();
980        write!(f, "[")?;
981        for (i, (_offset, a)) in iter.enumerate() {
982            if i > 0 {
983                write!(f, ", ")?;
984            }
985            write!(f, "{a}")?;
986        }
987        write!(f, "]")?;
988        write!(f, ")")
989    }
990}
991
992/// The supported hashing algorithms for ensuring integrity of a [`Message`]
993#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
994pub enum IntegrityAlgorithm {
995    /// SHA-1 algorithm
996    Sha1,
997    /// SHA-256 algorithm
998    Sha256,
999}
1000
1001impl<'a> Message<'a> {
1002    /// Create a new [`Message`] with the provided [`MessageType`] and transaction ID.
1003    ///
1004    /// Note you probably want to use one of the other helper constructors instead.
1005    ///
1006    /// # Examples
1007    ///
1008    /// ```
1009    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1010    /// #     MessageWrite, BINDING};
1011    /// let mtype = MessageType::from_class_method(MessageClass::Indication, BINDING);
1012    /// let message = Message::builder(mtype, 0.into(), MessageWriteVec::new()).finish();
1013    /// let message = Message::from_bytes(&message).unwrap();
1014    /// assert!(message.has_class(MessageClass::Indication));
1015    /// assert!(message.has_method(BINDING));
1016    /// ```
1017    pub fn builder<B: MessageWrite>(
1018        mtype: MessageType,
1019        transaction_id: TransactionId,
1020        mut write: B,
1021    ) -> B {
1022        let mut data = [0; 20];
1023        MessageHeader::new(mtype, transaction_id, 0).write_into(&mut data);
1024        write.push_data(&data);
1025        write
1026    }
1027
1028    /// Create a new request [`Message`] of the provided method.
1029    ///
1030    /// # Examples
1031    ///
1032    /// ```
1033    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1034    /// #     MessageWrite, BINDING};
1035    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
1036    /// let data = message.finish();
1037    /// let message = Message::from_bytes(&data).unwrap();
1038    /// assert!(message.has_class(MessageClass::Request));
1039    /// assert!(message.has_method(BINDING));
1040    /// ```
1041    pub fn builder_request<B: MessageWrite>(method: Method, write: B) -> B {
1042        Message::builder(
1043            MessageType::from_class_method(MessageClass::Request, method),
1044            TransactionId::generate(),
1045            write,
1046        )
1047    }
1048
1049    /// Create a new success [`Message`] response from the provided request.
1050    ///
1051    /// # Panics
1052    ///
1053    /// When a non-request [`Message`] is passed as the original input [`Message`]
1054    ///
1055    /// # Examples
1056    ///
1057    /// ```
1058    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1059    /// #      MessageWrite, BINDING};
1060    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
1061    /// let data = message.finish();
1062    /// let message = Message::from_bytes(&data).unwrap();
1063    /// let success = Message::builder_success(&message, MessageWriteVec::new()).finish();
1064    /// let success = Message::from_bytes(&success).unwrap();
1065    /// assert!(success.has_class(MessageClass::Success));
1066    /// assert!(success.has_method(BINDING));
1067    /// ```
1068    pub fn builder_success<B: MessageWrite>(orig: &Message, write: B) -> B {
1069        if !orig.has_class(MessageClass::Request) {
1070            panic!(
1071                "A success response message was attempted to be created from a non-request message"
1072            );
1073        }
1074        Message::builder(
1075            MessageType::from_class_method(MessageClass::Success, orig.method()),
1076            orig.transaction_id(),
1077            write,
1078        )
1079    }
1080
1081    /// Create a new error [`Message`] response from the provided request.
1082    ///
1083    /// # Panics
1084    ///
1085    /// When a non-request [`Message`] is passed as the original input [`Message`]
1086    ///
1087    /// # Examples
1088    ///
1089    /// ```
1090    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1091    /// #     MessageWrite, BINDING};
1092    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
1093    /// let data = message.finish();
1094    /// let message = Message::from_bytes(&data).unwrap();
1095    /// let error = Message::builder_error(&message, MessageWriteVec::new()).finish();
1096    /// let error = Message::from_bytes(&error).unwrap();
1097    /// assert!(error.has_class(MessageClass::Error));
1098    /// assert!(error.has_method(BINDING));
1099    /// ```
1100    pub fn builder_error<B: MessageWrite>(orig: &Message, write: B) -> B {
1101        if !orig.has_class(MessageClass::Request) {
1102            panic!(
1103                "An error response message was attempted to be created from a non-request message"
1104            );
1105        }
1106        Message::builder(
1107            MessageType::from_class_method(MessageClass::Error, orig.method()),
1108            orig.transaction_id(),
1109            write,
1110        )
1111    }
1112
1113    /// Create a new indication [`Message`] of the provided method.
1114    ///
1115    /// # Examples
1116    ///
1117    /// ```
1118    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1119    /// #     MessageWrite, BINDING};
1120    /// let message = Message::builder_indication(BINDING, MessageWriteVec::new());
1121    /// let data = message.finish();
1122    /// let message = Message::from_bytes(&data).unwrap();
1123    /// assert!(message.has_class(MessageClass::Indication));
1124    /// assert!(message.has_method(BINDING));
1125    /// ```
1126    pub fn builder_indication<B: MessageWrite>(method: Method, write: B) -> B {
1127        Message::builder(
1128            MessageType::from_class_method(MessageClass::Indication, method),
1129            TransactionId::generate(),
1130            write,
1131        )
1132    }
1133
1134    /// Retrieve the [`MessageType`] of a [`Message`].
1135    ///
1136    /// # Examples
1137    ///
1138    /// ```
1139    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1140    /// #     MessageWrite, BINDING};
1141    /// let message = Message::builder_request(BINDING, MessageWriteVec::new());
1142    /// let data = message.finish();
1143    /// let message = Message::from_bytes(&data).unwrap();
1144    /// assert!(message.get_type().has_class(MessageClass::Request));
1145    /// assert!(message.get_type().has_method(BINDING));
1146    /// ```
1147    pub fn get_type(&self) -> MessageType {
1148        MessageType::try_from(&self.data[..2]).unwrap()
1149    }
1150
1151    /// Retrieve the [`MessageClass`] of a [`Message`].
1152    ///
1153    /// # Examples
1154    ///
1155    /// ```
1156    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1157    /// #     MessageWrite, BINDING};
1158    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1159    /// let message = Message::from_bytes(&message).unwrap();
1160    /// assert_eq!(message.class(), MessageClass::Request);
1161    /// ```
1162    pub fn class(&self) -> MessageClass {
1163        self.get_type().class()
1164    }
1165
1166    /// Returns whether the [`Message`] is of the specified [`MessageClass`]
1167    ///
1168    /// # Examples
1169    ///
1170    /// ```
1171    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1172    /// #     MessageWrite, BINDING};
1173    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1174    /// let message = Message::from_bytes(&message).unwrap();
1175    /// assert!(message.has_class(MessageClass::Request));
1176    /// ```
1177    pub fn has_class(&self, cls: MessageClass) -> bool {
1178        self.class() == cls
1179    }
1180
1181    /// Returns whether the [`Message`] is a response.
1182    ///
1183    /// This means that the [`Message`] has a class of either success or error.
1184    ///
1185    /// # Examples
1186    ///
1187    /// ```
1188    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1189    /// #     MessageWrite, BINDING};
1190    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1191    /// let message = Message::from_bytes(&message).unwrap();
1192    /// assert_eq!(message.is_response(), false);
1193    ///
1194    /// let error = Message::builder_error(&message, MessageWriteVec::new()).finish();
1195    /// let error = Message::from_bytes(&error).unwrap();
1196    /// assert_eq!(error.is_response(), true);
1197    ///
1198    /// let success = Message::builder_success(&message, MessageWriteVec::new()).finish();
1199    /// let success = Message::from_bytes(&success).unwrap();
1200    /// assert_eq!(success.is_response(), true);
1201    /// ```
1202    pub fn is_response(&self) -> bool {
1203        self.class().is_response()
1204    }
1205
1206    /// Retrieves the method of the [`Message`].
1207    ///
1208    /// # Examples
1209    ///
1210    /// ```
1211    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1212    /// #     MessageWrite, BINDING};
1213    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1214    /// let message = Message::from_bytes(&message).unwrap();
1215    /// assert_eq!(message.method(), BINDING);
1216    /// ```
1217    pub fn method(&self) -> Method {
1218        self.get_type().method()
1219    }
1220
1221    /// Returns whether the [`Message`] is of the specified method.
1222    ///
1223    /// # Examples
1224    ///
1225    /// ```
1226    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1227    /// #     Method, MessageWrite, BINDING};
1228    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1229    /// let message = Message::from_bytes(&message).unwrap();
1230    /// assert!(message.has_method(BINDING));
1231    /// assert!(!message.has_method(Method::new(0)));
1232    /// ```
1233    pub fn has_method(&self, method: Method) -> bool {
1234        self.method() == method
1235    }
1236
1237    /// Retrieves the 96-bit transaction ID of the [`Message`]
1238    ///
1239    /// # Examples
1240    ///
1241    /// ```
1242    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1243    /// #     MessageWrite, BINDING, TransactionId};
1244    /// let mtype = MessageType::from_class_method(MessageClass::Request, BINDING);
1245    /// let transaction_id = TransactionId::generate();
1246    /// let message = Message::builder(mtype, transaction_id, MessageWriteVec::new()).finish();
1247    /// let message = Message::from_bytes(&message).unwrap();
1248    /// assert_eq!(message.transaction_id(), transaction_id);
1249    /// ```
1250    pub fn transaction_id(&self) -> TransactionId {
1251        BigEndian::read_u128(&self.data[4..]).into()
1252    }
1253
1254    /// Deserialize a STUN `Message` from its network bytes.
1255    ///
1256    /// This function will ensure that any fingerprint contained within matches the message
1257    /// contents and return errors on failure.
1258    ///
1259    /// Any message integrity value (as required by the STUN usage) should be checked in addition
1260    /// by calling [`Message::validate_integrity`].
1261    ///
1262    /// # Examples
1263    ///
1264    /// ```
1265    /// # use stun_types::attribute::{RawAttribute, Attribute};
1266    /// # use stun_types::message::{Message, MessageType, MessageClass, BINDING};
1267    /// let msg_data = [0, 1, 0, 8, 33, 18, 164, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 232, 0, 1, 0, 1, 3, 0, 0, 0];
1268    /// let message = Message::from_bytes(&msg_data).unwrap();
1269    /// let attr = RawAttribute::new(1.into(), &[3]);
1270    /// let msg_attr = message.raw_attribute(1.into()).unwrap();
1271    /// assert_eq!(msg_attr, attr);
1272    /// assert_eq!(message.get_type(), MessageType::from_class_method(MessageClass::Request, BINDING));
1273    /// assert_eq!(message.transaction_id(), 1000.into());
1274    /// ```
1275    #[tracing::instrument(
1276        name = "message_from_bytes",
1277        level = "trace",
1278        skip(data),
1279        fields(
1280            data.len = data.len()
1281        )
1282    )]
1283    pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
1284        let orig_data = data;
1285
1286        let header = MessageHeader::from_bytes(data)?;
1287        let mlength = header.data_length() as usize;
1288        if mlength + MessageHeader::LENGTH > data.len() {
1289            // mlength + header
1290            warn!(
1291                "malformed advertised size {} and data size {} don't match",
1292                mlength + 20,
1293                data.len()
1294            );
1295            return Err(StunParseError::Truncated {
1296                expected: mlength + MessageHeader::LENGTH,
1297                actual: data.len(),
1298            });
1299        }
1300
1301        let ending_attributes = [
1302            MessageIntegrity::TYPE,
1303            MessageIntegritySha256::TYPE,
1304            Fingerprint::TYPE,
1305        ];
1306        // XXX: maybe use small/tinyvec?
1307        let mut seen_ending_attributes = [AttributeType::new(0); 3];
1308        let mut seen_ending_len = 0;
1309        let mut data_offset = MessageHeader::LENGTH;
1310        let mut integrity_offset = None;
1311        for attr in MessageRawAttributesIter::new(data) {
1312            let (_offset, attr) = attr.inspect_err(|e| {
1313                warn!("failed to parse message attribute at offset {data_offset}: {e}",);
1314            })?;
1315
1316            // if we have seen any ending attributes, then there is only a fixed set of attributes
1317            // that are allowed.
1318            if seen_ending_len > 0 && !ending_attributes.contains(&attr.get_type()) {
1319                if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1320                    warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1321                    return Ok(Message {
1322                        data: orig_data,
1323                        integrity_offset,
1324                    });
1325                } else {
1326                    // only attribute valid after MESSAGE_INTEGRITY is FINGERPRINT
1327                    warn!(
1328                        "unexpected attribute {} after MESSAGE_INTEGRITY",
1329                        attr.get_type()
1330                    );
1331                    return Ok(Message {
1332                        data: orig_data,
1333                        integrity_offset,
1334                    });
1335                }
1336            }
1337
1338            if ending_attributes.contains(&attr.get_type()) {
1339                if seen_ending_attributes.contains(&attr.get_type()) {
1340                    if seen_ending_attributes.contains(&Fingerprint::TYPE) {
1341                        warn!("unexpected attribute {} after FINGERPRINT", attr.get_type());
1342                        return Ok(Message {
1343                            data: orig_data,
1344                            integrity_offset,
1345                        });
1346                    } else {
1347                        // only attribute valid after MESSAGE_INTEGRITY is FINGERPRINT
1348                        warn!(
1349                            "unexpected attribute {} after MESSAGE_INTEGRITY",
1350                            attr.get_type()
1351                        );
1352                        return Ok(Message {
1353                            data: orig_data,
1354                            integrity_offset,
1355                        });
1356                    }
1357                } else {
1358                    seen_ending_attributes[seen_ending_len] = attr.get_type();
1359                    seen_ending_len += 1;
1360                    integrity_offset.get_or_insert(NonZeroUsize::new(data_offset).unwrap());
1361                    // need credentials to validate the integrity of the message
1362                }
1363            }
1364            let padded_len = attr.padded_len();
1365            if attr.get_type() == Fingerprint::TYPE {
1366                let f = Fingerprint::from_raw_ref(&attr)?;
1367                let msg_fingerprint = f.fingerprint();
1368                let mut header = [0; 4];
1369                header[0] = orig_data[0];
1370                header[1] = orig_data[1];
1371                BigEndian::write_u16(
1372                    &mut header[2..4],
1373                    (data_offset + padded_len - MessageHeader::LENGTH) as u16,
1374                );
1375                let fingerprint_data = &orig_data[4..data_offset];
1376                let calculated_fingerprint = Fingerprint::compute(&[&header, fingerprint_data]);
1377                if &calculated_fingerprint != msg_fingerprint {
1378                    warn!(
1379                        "fingerprint mismatch {:?} != {:?}",
1380                        calculated_fingerprint, msg_fingerprint
1381                    );
1382                    return Err(StunParseError::FingerprintMismatch);
1383                }
1384            }
1385            data_offset += padded_len;
1386        }
1387        Ok(Message {
1388            data: orig_data,
1389            integrity_offset,
1390        })
1391    }
1392
1393    /// Validates the MESSAGE_INTEGRITY attribute with the provided credentials.
1394    ///
1395    /// # Examples
1396    ///
1397    /// ```
1398    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1399    /// #     MessageWrite, MessageWriteExt, BINDING, MessageIntegrityCredentials,
1400    /// #     LongTermKeyCredentials, IntegrityAlgorithm};
1401    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1402    /// let credentials = LongTermKeyCredentials::new(
1403    ///     "user".to_owned(),
1404    ///     "pass".to_owned(),
1405    ///     "realm".to_owned()
1406    /// ).into();
1407    /// assert!(message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256).is_ok());
1408    /// let data = message.finish();
1409    /// let message = Message::from_bytes(&data).unwrap();
1410    /// assert!(message.validate_integrity(&credentials).is_ok());
1411    /// ```
1412    pub fn validate_integrity(
1413        &self,
1414        credentials: &MessageIntegrityCredentials,
1415    ) -> Result<IntegrityAlgorithm, ValidateError> {
1416        let offset = self
1417            .integrity_offset
1418            .ok_or(ValidateError::Parse(StunParseError::MissingAttribute(
1419                MessageIntegrity::TYPE,
1420            )))?
1421            .get();
1422
1423        let iter = MessageAttributesIter::at_offset(self.data, offset);
1424        let mut raw_sha1 = None;
1425        let mut raw_sha256 = None;
1426        for (offset, raw_attr) in iter {
1427            match raw_attr.get_type() {
1428                MessageIntegrity::TYPE => {
1429                    raw_sha1 = Some((offset, raw_attr));
1430                }
1431                MessageIntegritySha256::TYPE => {
1432                    raw_sha256 = Some((offset, raw_attr));
1433                }
1434                _ => (),
1435            }
1436        }
1437
1438        let integrity_sha1;
1439        let integrity_sha256;
1440        let (algo, msg_hmac, offset) = match (raw_sha1, raw_sha256) {
1441            (_, Some((offset, sha256))) => {
1442                integrity_sha256 = MessageIntegritySha256::try_from(&sha256)?;
1443                (IntegrityAlgorithm::Sha256, integrity_sha256.hmac(), offset)
1444            }
1445            (Some((offset, sha1)), None) => {
1446                integrity_sha1 = MessageIntegrity::try_from(&sha1)?;
1447                (
1448                    IntegrityAlgorithm::Sha1,
1449                    integrity_sha1.hmac().as_slice(),
1450                    offset,
1451                )
1452            }
1453            (None, None) => {
1454                return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE).into())
1455            }
1456        };
1457        let key = credentials.make_key(algo);
1458        self.validate_integrity_with_hmac(algo, msg_hmac, &key, offset)
1459    }
1460
1461    /// Validates the MESSAGE_INTEGRITY attribute with the provided credential [`IntegrityKey`].
1462    pub fn validate_integrity_with_key(
1463        &self,
1464        key: &IntegrityKey,
1465    ) -> Result<IntegrityAlgorithm, ValidateError> {
1466        let offset = self
1467            .integrity_offset
1468            .ok_or(ValidateError::Parse(StunParseError::MissingAttribute(
1469                MessageIntegrity::TYPE,
1470            )))?
1471            .get();
1472
1473        let iter = MessageAttributesIter::at_offset(self.data, offset);
1474        let mut raw_sha1 = None;
1475        let mut raw_sha256 = None;
1476        for (offset, raw_attr) in iter {
1477            match raw_attr.get_type() {
1478                MessageIntegrity::TYPE => {
1479                    raw_sha1 = Some((offset, raw_attr));
1480                }
1481                MessageIntegritySha256::TYPE => {
1482                    raw_sha256 = Some((offset, raw_attr));
1483                }
1484                _ => (),
1485            }
1486        }
1487
1488        let integrity_sha1;
1489        let integrity_sha256;
1490        let (algo, msg_hmac, offset) = if let Some(algo) = key.key_algorithm {
1491            match (algo, raw_sha1, raw_sha256) {
1492                (IntegrityAlgorithm::Sha256, _, Some((offset, sha256))) => {
1493                    integrity_sha256 = MessageIntegritySha256::try_from(&sha256)?;
1494                    (algo, integrity_sha256.hmac(), offset)
1495                }
1496                (IntegrityAlgorithm::Sha1, Some((offset, sha1)), _) => {
1497                    integrity_sha1 = MessageIntegrity::try_from(&sha1)?;
1498                    (algo, integrity_sha1.hmac().as_slice(), offset)
1499                }
1500                _ => return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE).into()),
1501            }
1502        } else {
1503            match (raw_sha1, raw_sha256) {
1504                (_, Some((offset, sha256))) => {
1505                    integrity_sha256 = MessageIntegritySha256::try_from(&sha256)?;
1506                    (IntegrityAlgorithm::Sha256, integrity_sha256.hmac(), offset)
1507                }
1508                (Some((offset, sha1)), None) => {
1509                    integrity_sha1 = MessageIntegrity::try_from(&sha1)?;
1510                    (
1511                        IntegrityAlgorithm::Sha1,
1512                        integrity_sha1.hmac().as_slice(),
1513                        offset,
1514                    )
1515                }
1516                (None, None) => {
1517                    return Err(StunParseError::MissingAttribute(MessageIntegrity::TYPE).into())
1518                }
1519            }
1520        };
1521        self.validate_integrity_with_hmac(algo, msg_hmac, key, offset)
1522    }
1523
1524    #[tracing::instrument(
1525        name = "message_validate_integrity_with_hmac",
1526        level = "trace",
1527        skip(self, key, msg_hmac),
1528        fields(
1529            msg.transaction = %self.transaction_id(),
1530        )
1531    )]
1532    fn validate_integrity_with_hmac(
1533        &self,
1534        algo: IntegrityAlgorithm,
1535        msg_hmac: &[u8],
1536        key: &IntegrityKey,
1537        integrity_offset: usize,
1538    ) -> Result<IntegrityAlgorithm, ValidateError> {
1539        if key.key_algorithm.is_some_and(|key_algo| key_algo != algo) {
1540            debug!(
1541                "Key algorithm ({:?}) does not match algo ({algo:?})",
1542                key.key_algorithm
1543            );
1544            return Err(StunParseError::DataMismatch.into());
1545        }
1546        // find the location of the original MessageIntegrity attribute.
1547        debug_assert!(self.data.len() >= MessageHeader::LENGTH);
1548        debug_assert!(integrity_offset >= MessageHeader::LENGTH);
1549        debug_assert!(integrity_offset < self.data.len());
1550        let mut data = &self.data[integrity_offset..];
1551        let mut data_offset = integrity_offset;
1552        while !data.is_empty() {
1553            let attr = RawAttribute::from_bytes(data)?;
1554            if algo == IntegrityAlgorithm::Sha1 && attr.get_type() == MessageIntegrity::TYPE {
1555                let msg = MessageIntegrity::try_from(&attr)?;
1556                debug_assert!(msg.hmac().as_slice() == msg_hmac);
1557
1558                // HMAC is computed using all the data up to (exclusive of) the MESSAGE_INTEGRITY
1559                // but with a length field including the MESSAGE_INTEGRITY attribute...
1560                let mut header = [0; 4];
1561                header[0] = self.data[0];
1562                header[1] = self.data[1];
1563                let hmac_data = &self.data[4..data_offset];
1564                BigEndian::write_u16(
1565                    &mut header[2..4],
1566                    data_offset as u16 + 24 - MessageHeader::LENGTH as u16,
1567                );
1568                if MessageIntegrity::verify(
1569                    &[header.as_slice(), hmac_data],
1570                    key,
1571                    msg_hmac.try_into().unwrap(),
1572                ) {
1573                    return Ok(algo);
1574                } else {
1575                    return Err(ValidateError::IntegrityFailed);
1576                }
1577            } else if algo == IntegrityAlgorithm::Sha256
1578                && attr.get_type() == MessageIntegritySha256::TYPE
1579            {
1580                let msg = MessageIntegritySha256::try_from(&attr)?;
1581                debug_assert!(msg.hmac() == msg_hmac);
1582
1583                // HMAC is computed using all the data up to (exclusive of) the MESSAGE_INTEGRITY
1584                // but with a length field including the MESSAGE_INTEGRITY attribute...
1585                let mut header = [0; 4];
1586                header[0] = self.data[0];
1587                header[1] = self.data[1];
1588                let hmac_data = &self.data[4..data_offset];
1589                BigEndian::write_u16(
1590                    &mut header[2..4],
1591                    data_offset as u16 + attr.padded_len() as u16 - MessageHeader::LENGTH as u16,
1592                );
1593                if MessageIntegritySha256::verify(&[&header, hmac_data], key, msg_hmac) {
1594                    return Ok(algo);
1595                } else {
1596                    return Err(ValidateError::IntegrityFailed);
1597                }
1598            }
1599            let padded_len = attr.padded_len();
1600            // checked when initially parsing.
1601            debug_assert!(padded_len <= data.len());
1602            data = &data[padded_len..];
1603            data_offset += padded_len;
1604        }
1605
1606        // Either there is no integrity (checked earlier), or the integrity was found and checked
1607        // by the loop above.
1608        unreachable!();
1609    }
1610
1611    /// Retrieve the nth `RawAttribute` with a particular [`AttributeType`] from this `Message`.
1612    ///
1613    /// # Examples
1614    ///
1615    /// Retrieve a`RawAttribute`
1616    ///
1617    /// ```
1618    /// # use stun_types::attribute::{RawAttribute, Attribute};
1619    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1620    /// #     MessageWrite, MessageWriteExt, BINDING};
1621    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1622    /// let attr = RawAttribute::new(1.into(), &[3]);
1623    /// assert!(message.add_attribute(&attr).is_ok());
1624    /// assert!(message.add_attribute(&attr).is_ok());
1625    /// let message = message.finish();
1626    /// let message = Message::from_bytes(&message).unwrap();
1627    /// assert_eq!(message.nth_raw_attribute(1.into(), 1).unwrap(), attr);
1628    /// ```
1629    pub fn nth_raw_attribute(&self, atype: AttributeType, n: usize) -> Option<RawAttribute<'_>> {
1630        self.nth_raw_attribute_and_offset(atype, n)
1631            .map(|(_offset, attr)| attr)
1632    }
1633
1634    /// Retrieve the first `RawAttribute` of a particular `AttributeTye` from this `Message`.
1635    ///
1636    /// The is equivalent to `Message::nth_raw_attribute(0)`.
1637    pub fn raw_attribute(&self, atype: AttributeType) -> Option<RawAttribute<'_>> {
1638        self.nth_raw_attribute(atype, 0)
1639    }
1640
1641    /// Retrieve the nth `RawAttribute` of a particular `AttributeType` from this `Message` with
1642    /// it's byte offset.
1643    ///
1644    /// The offset is from the start of the 4 byte Attribute header.
1645    ///
1646    /// # Examples
1647    ///
1648    /// Retrieve a`RawAttribute`.
1649    ///
1650    /// ```
1651    /// # use stun_types::attribute::{RawAttribute, Attribute};
1652    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1653    /// #     MessageWrite, MessageWriteExt, BINDING};
1654    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1655    /// let attr = RawAttribute::new(1.into(), &[3]);
1656    /// assert!(message.add_attribute(&attr).is_ok());
1657    /// assert!(message.add_attribute(&attr).is_ok());
1658    /// let message = message.finish();
1659    /// let message = Message::from_bytes(&message).unwrap();
1660    /// assert_eq!(message.nth_raw_attribute_and_offset(1.into(), 1).unwrap(), (28, attr));
1661    /// ```
1662    #[tracing::instrument(
1663        name = "message_nth_raw_attribute_and_offset",
1664        level = "trace",
1665        skip(self, atype),
1666        fields(
1667            msg.transaction = %self.transaction_id(),
1668            attribute_type = %atype,
1669        )
1670    )]
1671    pub fn nth_raw_attribute_and_offset(
1672        &self,
1673        atype: AttributeType,
1674        n: usize,
1675    ) -> Option<(usize, RawAttribute<'_>)> {
1676        if let Some((offset, attr)) = self
1677            .iter_attributes()
1678            .filter(|(_offset, attr)| attr.get_type() == atype)
1679            .nth(n)
1680        {
1681            trace!("found attribute at offset: {offset}");
1682            Some((offset, attr))
1683        } else {
1684            trace!("could not find attribute");
1685            None
1686        }
1687    }
1688
1689    /// Retrieve the first `RawAttribute` of a particular `AttributeType` from this `Message` with
1690    /// it's byte offset.
1691    ///
1692    /// This equivalent to calling `Message::nth_raw_attribute_and_offset(0)`.
1693    pub fn raw_attribute_and_offset(
1694        &self,
1695        atype: AttributeType,
1696    ) -> Option<(usize, RawAttribute<'_>)> {
1697        self.nth_raw_attribute_and_offset(atype, 0)
1698    }
1699
1700    /// Retrieve the nth `Attribute` of a particular `AttributeType` from this `Message`.
1701    ///
1702    /// This will error with [`StunParseError::MissingAttribute`] if the attribute does not exist.
1703    /// Otherwise, other parsing errors of the data may be returned specific to the attribute
1704    /// implementation provided.
1705    ///
1706    /// # Examples
1707    ///
1708    /// Retrieve an `Attribute`
1709    ///
1710    /// ```
1711    /// # use stun_types::attribute::{Software, Attribute};
1712    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1713    /// #     MessageWrite, MessageWriteExt, BINDING};
1714    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1715    /// let attr = Software::new("stun-types").unwrap();
1716    /// assert!(message.add_attribute(&attr).is_ok());
1717    /// let message = message.finish();
1718    /// let message = Message::from_bytes(&message).unwrap();
1719    /// assert_eq!(message.attribute::<Software>().unwrap(), attr);
1720    /// ```
1721    pub fn nth_attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1722        &'a self,
1723        n: usize,
1724    ) -> Result<A, StunParseError> {
1725        self.nth_attribute_and_offset(n).map(|(_offset, attr)| attr)
1726    }
1727
1728    /// Retrieve the first `Attribute` of a particular `AttributeType` from this `Message`.
1729    ///
1730    /// This equivalent to calling `Message::nth_attribute(0)`.
1731    pub fn attribute<A: AttributeFromRaw<'a> + AttributeStaticType>(
1732        &'a self,
1733    ) -> Result<A, StunParseError> {
1734        self.nth_attribute(0)
1735    }
1736
1737    /// Retrieve the nth `Attribute` of a particular `AttributeType` from this `Message` and it's
1738    /// offset in the original data.
1739    ///
1740    /// This will error with [`StunParseError::MissingAttribute`] if the attribute does not exist.
1741    /// Otherwise, other parsing errors of the data may be returned specific to the attribute
1742    /// implementation provided.
1743    ///
1744    /// The offset is from the start of the 4 byte [`Attribute`] header.
1745    ///
1746    /// # Examples
1747    ///
1748    /// Retrieve an `Attribute`
1749    ///
1750    /// ```
1751    /// # use stun_types::attribute::{Software, Attribute};
1752    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1753    /// #     MessageWrite, MessageWriteExt, BINDING};
1754    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
1755    /// let attr = Software::new("stun-types").unwrap();
1756    /// assert!(message.add_attribute(&attr).is_ok());
1757    /// assert!(message.add_attribute(&attr).is_ok());
1758    /// let message = message.finish();
1759    /// let message = Message::from_bytes(&message).unwrap();
1760    /// assert_eq!(message.nth_attribute_and_offset::<Software>(1).unwrap(), (36, attr));
1761    /// ```
1762    pub fn nth_attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1763        &'a self,
1764        n: usize,
1765    ) -> Result<(usize, A), StunParseError> {
1766        self.nth_raw_attribute_and_offset(A::TYPE, n)
1767            .ok_or(StunParseError::MissingAttribute(A::TYPE))
1768            .and_then(|(offset, raw)| A::from_raw(raw).map(|attr| (offset, attr)))
1769    }
1770
1771    /// Retrieve the first `Attribute` of a particular `AttributeType` from this `Message` and it's
1772    /// offset in the original data.
1773    ///
1774    /// This equivalent to calling `Message::nth_attribute_and_offset(0)`.
1775    pub fn attribute_and_offset<A: AttributeFromRaw<'a> + AttributeStaticType>(
1776        &'a self,
1777    ) -> Result<(usize, A), StunParseError> {
1778        self.nth_attribute_and_offset(0)
1779    }
1780
1781    /// Returns an iterator over the attributes (with their byte offset) in the [`Message`].
1782    pub fn iter_attributes(&self) -> impl Iterator<Item = (usize, RawAttribute<'_>)> {
1783        MessageAttributesIter::new(self.data)
1784    }
1785
1786    /// Check that a message [`Message`] only contains required attributes that are supported and
1787    /// have at least some set of required attributes.
1788    ///
1789    /// Returns an appropriate error message on failure to meet these requirements.
1790    ///
1791    /// # Examples
1792    ///
1793    /// ```
1794    /// # use stun_types::attribute::*;
1795    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1796    /// #     MessageWrite, MessageWriteExt, BINDING};
1797    /// # use core::convert::TryInto;
1798    /// let mut builder = Message::builder_request(BINDING, MessageWriteVec::new());
1799    /// let message = builder.finish();
1800    /// let message = Message::from_bytes(&message).unwrap();
1801    /// // If nothing is required, no error response is returned
1802    /// assert!(matches!(Message::check_attribute_types(&message, &[], &[], MessageWriteVec::new()), None));
1803    ///
1804    /// // If an atttribute is required that is not in the message, then an error response message
1805    /// // is generated
1806    /// let error_msg = Message::check_attribute_types(
1807    ///     &message,
1808    ///     &[],
1809    ///     &[Software::TYPE],
1810    ///     MessageWriteVec::new(),
1811    /// ).unwrap();
1812    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1813    /// let error_msg = error_msg.finish();
1814    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1815    /// let error_code = error_msg.attribute::<ErrorCode>().unwrap();
1816    /// assert_eq!(error_code.code(), 400);
1817    ///
1818    /// let mut builder = Message::builder_request(BINDING, MessageWriteVec::new());
1819    /// let username = Username::new("user").unwrap();
1820    /// builder.add_attribute(&username).unwrap();
1821    /// let message = builder.finish();
1822    /// let message = Message::from_bytes(&message).unwrap();
1823    /// // If a Username is in the message but is not advertised as supported then an
1824    /// // 'UNKNOWN-ATTRIBUTES' error response is returned
1825    /// let error_msg = Message::check_attribute_types(&message, &[], &[], MessageWriteVec::new()).unwrap();
1826    /// let error_msg = error_msg.finish();
1827    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1828    /// assert!(error_msg.is_response());
1829    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1830    /// let error_code = error_msg.attribute::<ErrorCode>().unwrap();
1831    /// assert_eq!(error_code.code(), 420);
1832    /// assert!(error_msg.has_attribute(UnknownAttributes::TYPE));
1833    /// ```
1834    #[tracing::instrument(
1835        level = "trace",
1836        skip(msg, write),
1837        fields(
1838            msg.transaction = %msg.transaction_id(),
1839        )
1840    )]
1841    pub fn check_attribute_types<B: MessageWrite>(
1842        msg: &Message,
1843        supported: &[AttributeType],
1844        required_in_msg: &[AttributeType],
1845        write: B,
1846    ) -> Option<B> {
1847        // Attribute -> AttributeType
1848        let unsupported: Vec<AttributeType> = msg
1849            .iter_attributes()
1850            .map(|(_offset, a)| a.get_type())
1851            // attribute types that require comprehension but are not supported by the caller
1852            .filter(|at| at.comprehension_required() && !supported.contains(at))
1853            .collect();
1854        if !unsupported.is_empty() {
1855            warn!(
1856                "Message contains unknown comprehension required attributes {:?}, returning unknown attributes",
1857                unsupported
1858            );
1859            return Some(Message::unknown_attributes(msg, &unsupported, write));
1860        }
1861        let has_required_attribute_missing = required_in_msg
1862            .iter()
1863            // attribute types we need in the message -> failure -> Bad Request
1864            .any(|&at| {
1865                !msg.iter_attributes()
1866                    .map(|(_offset, a)| a.get_type())
1867                    .any(|a| a == at)
1868            });
1869        if has_required_attribute_missing {
1870            warn!("Message is missing required attributes, returning bad request");
1871            return Some(Message::bad_request(msg, write));
1872        }
1873        None
1874    }
1875
1876    /// Generate an error message with an [`ErrorCode`] attribute signalling 'Unknown Attribute'
1877    /// and an [`UnknownAttributes`] attribute containing the attributes that are unknown..
1878    ///
1879    /// # Examples
1880    ///
1881    /// ```
1882    /// # use stun_types::message::{Message, MessageWriteVec, MessageWrite, BINDING};
1883    /// # use stun_types::attribute::*;
1884    /// # use core::convert::TryInto;
1885    /// let msg = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1886    /// let msg = Message::from_bytes(&msg).unwrap();
1887    /// let error_msg = Message::unknown_attributes(&msg, &[Username::TYPE], MessageWriteVec::new()).finish();
1888    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1889    /// assert!(error_msg.is_response());
1890    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1891    /// let error_code = error_msg.attribute::<ErrorCode>().unwrap();
1892    /// assert_eq!(error_code.code(), 420);
1893    /// let unknown = error_msg.attribute::<UnknownAttributes>().unwrap();
1894    /// assert!(unknown.has_attribute(Username::TYPE));
1895    /// ```
1896    pub fn unknown_attributes<B: MessageWrite>(
1897        src: &Message,
1898        attributes: &[AttributeType],
1899        write: B,
1900    ) -> B {
1901        let mut out = Message::builder_error(src, write);
1902        let software = Software::new("stun-types").unwrap();
1903        out.add_attribute(&software).unwrap();
1904        let error = ErrorCode::new(420, "Unknown Attributes").unwrap();
1905        out.add_attribute(&error).unwrap();
1906        let unknown = UnknownAttributes::new(attributes);
1907        if !attributes.is_empty() {
1908            out.add_attribute(&unknown).unwrap();
1909        }
1910        out
1911    }
1912
1913    /// Generate an error message with an [`ErrorCode`] attribute signalling a 'Bad Request'.
1914    ///
1915    /// # Examples
1916    ///
1917    /// ```
1918    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1919    /// #     MessageWrite, BINDING};
1920    /// # use stun_types::attribute::*;
1921    /// # use core::convert::TryInto;
1922    /// let msg = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
1923    /// let msg = Message::from_bytes(&msg).unwrap();
1924    /// let error_msg = Message::bad_request(&msg, MessageWriteVec::new()).finish();
1925    /// let error_msg = Message::from_bytes(&error_msg).unwrap();
1926    /// assert!(error_msg.has_attribute(ErrorCode::TYPE));
1927    /// let error_code =  error_msg.attribute::<ErrorCode>().unwrap();
1928    /// assert_eq!(error_code.code(), 400);
1929    /// ```
1930    pub fn bad_request<B: MessageWrite>(src: &Message, write: B) -> B {
1931        let mut out = Message::builder_error(src, write);
1932        let software = Software::new("stun-types").unwrap();
1933        out.add_attribute(&software).unwrap();
1934        let error = ErrorCode::new(400, "Bad Request").unwrap();
1935        out.add_attribute(&error).unwrap();
1936        out
1937    }
1938
1939    /// Whether this message contains an attribute of the specified type.
1940    ///
1941    /// # Examples
1942    ///
1943    /// ```
1944    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
1945    /// #     MessageWrite, MessageWriteExt, BINDING};
1946    /// # use stun_types::attribute::{Software, Attribute, AttributeStaticType};
1947    /// let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
1948    /// let attr = Software::new("stun-types").unwrap();
1949    /// assert!(msg.add_attribute(&attr).is_ok());
1950    /// let msg = msg.finish();
1951    /// let msg = Message::from_bytes(&msg).unwrap();
1952    /// assert!(msg.has_attribute(Software::TYPE));
1953    /// ```
1954    pub fn has_attribute(&self, atype: AttributeType) -> bool {
1955        self.iter_attributes()
1956            .any(|(_offset, attr)| attr.get_type() == atype)
1957    }
1958
1959    /// Returns the underlying slice.
1960    pub fn as_bytes(&self) -> &[u8] {
1961        self.data
1962    }
1963}
1964impl<'a> TryFrom<&'a [u8]> for Message<'a> {
1965    type Error = StunParseError;
1966
1967    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
1968        Message::from_bytes(value)
1969    }
1970}
1971
1972impl AsRef<[u8]> for Message<'_> {
1973    fn as_ref(&self) -> &[u8] {
1974        self.data
1975    }
1976}
1977
1978#[derive(Debug)]
1979struct MessageRawAttributesIter<'a> {
1980    data: &'a [u8],
1981    data_i: usize,
1982}
1983
1984impl<'a> MessageRawAttributesIter<'a> {
1985    fn new(data: &'a [u8]) -> Self {
1986        Self::at_offset(data, MessageHeader::LENGTH)
1987    }
1988
1989    fn at_offset(data: &'a [u8], offset: usize) -> Self {
1990        Self {
1991            data,
1992            data_i: offset,
1993        }
1994    }
1995}
1996
1997impl<'a> Iterator for MessageRawAttributesIter<'a> {
1998    type Item = Result<(usize, RawAttribute<'a>), StunParseError>;
1999
2000    fn next(&mut self) -> Option<Self::Item> {
2001        if self.data_i >= self.data.len() {
2002            return None;
2003        }
2004
2005        match RawAttribute::from_bytes(&self.data[self.data_i..]) {
2006            Ok(attr) => {
2007                let padded_len = attr.padded_len();
2008                self.data_i += padded_len;
2009                if self.data_i > self.data.len() {
2010                    warn!(
2011                        "attribute {} extends past the end of the data",
2012                        attr.get_type()
2013                    );
2014                    return Some(Err(StunParseError::Truncated {
2015                        expected: self.data_i,
2016                        actual: self.data.len(),
2017                    }));
2018                }
2019                Some(Ok((self.data_i - padded_len, attr)))
2020            }
2021            Err(e) => {
2022                let offset = self.data_i;
2023                self.data_i = self.data.len();
2024                let e = match e {
2025                    StunParseError::Truncated { expected, actual } => StunParseError::Truncated {
2026                        expected: expected + 4 + offset,
2027                        actual: actual + 4 + offset,
2028                    },
2029                    StunParseError::TooLarge { expected, actual } => StunParseError::TooLarge {
2030                        expected: expected + 4 + offset,
2031                        actual: actual + 4 + offset,
2032                    },
2033                    e => e,
2034                };
2035                Some(Err(e))
2036            }
2037        }
2038    }
2039}
2040
2041#[doc(hidden)]
2042#[derive(Debug)]
2043pub struct MessageAttributesIter<'a> {
2044    header_parsed: bool,
2045    inner: MessageRawAttributesIter<'a>,
2046    last_attr_type: AttributeType,
2047    seen_message_integrity: bool,
2048}
2049
2050impl<'a> MessageAttributesIter<'a> {
2051    /// Construct an Iterator over the attributes of a [`Message`].
2052    ///
2053    /// The provided data is the entirety of the message data.
2054    ///
2055    /// Note: this entry point does not verify that the message passes integrity and fingerprint
2056    /// checks and therefore must be used with care on untrusted data. You should use
2057    /// [`Message::from_bytes`] and [`Message::validate_integrity`] to validate the integrity of a
2058    /// STUN [`Message`].
2059    pub fn new(data: &'a [u8]) -> Self {
2060        Self {
2061            header_parsed: false,
2062            inner: MessageRawAttributesIter::new(data),
2063            seen_message_integrity: false,
2064            last_attr_type: AttributeType::new(0),
2065        }
2066    }
2067
2068    fn at_offset(data: &'a [u8], offset: usize) -> Self {
2069        Self {
2070            header_parsed: true,
2071            inner: MessageRawAttributesIter::at_offset(data, offset),
2072            seen_message_integrity: false,
2073            last_attr_type: AttributeType::new(0),
2074        }
2075    }
2076}
2077
2078impl<'a> Iterator for MessageAttributesIter<'a> {
2079    type Item = (usize, RawAttribute<'a>);
2080
2081    fn next(&mut self) -> Option<Self::Item> {
2082        // nothing further to parse after Fingerprint
2083        if self.last_attr_type == Fingerprint::TYPE {
2084            return None;
2085        }
2086
2087        if !self.header_parsed {
2088            let Ok(hdr) = MessageHeader::from_bytes(self.inner.data) else {
2089                self.last_attr_type = Fingerprint::TYPE;
2090                return None;
2091            };
2092            if hdr.data_length() as usize + MessageHeader::LENGTH > self.inner.data.len() {
2093                self.last_attr_type = Fingerprint::TYPE;
2094                return None;
2095            }
2096            self.header_parsed = true;
2097        }
2098
2099        let (offset, attr) = self.inner.next()?.ok()?;
2100        let attr_type = attr.get_type();
2101        if self.seen_message_integrity {
2102            if self.last_attr_type != Fingerprint::TYPE && attr_type == Fingerprint::TYPE {
2103                self.last_attr_type = attr_type;
2104                return Some((offset, attr));
2105            }
2106            if self.last_attr_type == MessageIntegrity::TYPE
2107                && attr_type == MessageIntegritySha256::TYPE
2108            {
2109                self.last_attr_type = attr_type;
2110                return Some((offset, attr));
2111            }
2112            self.last_attr_type = Fingerprint::TYPE;
2113            return None;
2114        }
2115        if attr.get_type() == MessageIntegrity::TYPE
2116            || attr.get_type() == MessageIntegritySha256::TYPE
2117            || attr.get_type() == Fingerprint::TYPE
2118        {
2119            self.seen_message_integrity = true;
2120        }
2121        self.last_attr_type = attr.get_type();
2122
2123        Some((offset, attr))
2124    }
2125}
2126
2127#[allow(clippy::len_without_is_empty)]
2128/// Trait for implementing a writer for [`Message`]s.
2129pub trait MessageWrite {
2130    /// The output of this [`MessageWrite`].
2131    type Output;
2132    /// Return the maximum size of the output.  If the output data is not bound to a fixed size,
2133    /// `None` should be returned.
2134    fn max_size(&self) -> Option<usize> {
2135        None
2136    }
2137
2138    /// A mutable reference to the contained data.
2139    fn mut_data(&mut self) -> &mut [u8];
2140    /// A reference to the contained data.
2141    fn data(&self) -> &[u8];
2142    /// The length of the currently written data.
2143    fn len(&self) -> usize;
2144    /// Append the provided data to the end of the output.
2145    fn push_data(&mut self, data: &[u8]);
2146    /// Write an attribute to the end of the Message.
2147    fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite);
2148
2149    /// Return whether this [`MessageWrite`] contains a particular attribute.
2150    fn has_attribute(&self, atype: AttributeType) -> bool;
2151
2152    /// Return whether this [`MessageWrite`] contains any of the provided attributes and
2153    /// returns the attribute found.
2154    fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType>;
2155
2156    /// Finishes and returns the built Message.
2157    fn finish(self) -> Self::Output;
2158}
2159
2160/// Extension trait for [`MessageWrite`] providing helper functions.
2161pub trait MessageWriteExt: MessageWrite {
2162    /// Retrieve the [`MessageClass`] of a [`Message`].
2163    ///
2164    /// # Examples
2165    ///
2166    /// ```
2167    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2168    /// #     MessageWrite, BINDING};
2169    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2170    /// let message = Message::from_bytes(&message).unwrap();
2171    /// assert_eq!(message.class(), MessageClass::Request);
2172    /// ```
2173    fn get_type(&self) -> MessageType {
2174        MessageType::from_bytes(self.data()).unwrap()
2175    }
2176
2177    /// Retrieve the [`MessageClass`] of a [`Message`].
2178    ///
2179    /// # Examples
2180    ///
2181    /// ```
2182    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2183    /// #     MessageWrite, BINDING};
2184    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2185    /// let message = Message::from_bytes(&message).unwrap();
2186    /// assert_eq!(message.class(), MessageClass::Request);
2187    /// ```
2188    fn class(&self) -> MessageClass {
2189        self.get_type().class()
2190    }
2191
2192    /// Returns whether the [`Message`] is of the specified [`MessageClass`].
2193    ///
2194    /// # Examples
2195    ///
2196    /// ```
2197    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2198    /// #     MessageWrite, BINDING};
2199    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2200    /// let message = Message::from_bytes(&message).unwrap();
2201    /// assert!(message.has_class(MessageClass::Request));
2202    /// ```
2203    fn has_class(&self, cls: MessageClass) -> bool {
2204        self.class() == cls
2205    }
2206
2207    /// Returns whether the [`Message`] is a response.
2208    ///
2209    /// This means that the [`Message`] has a class of either success or error.
2210    ///
2211    /// # Examples
2212    ///
2213    /// ```
2214    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2215    /// #     MessageWrite, BINDING};
2216    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2217    /// let message = Message::from_bytes(&message).unwrap();
2218    /// assert_eq!(message.is_response(), false);
2219    ///
2220    /// let error = Message::builder_error(&message, MessageWriteVec::new()).finish();
2221    /// let error = Message::from_bytes(&error).unwrap();
2222    /// assert_eq!(error.is_response(), true);
2223    ///
2224    /// let success = Message::builder_success(&message, MessageWriteVec::new()).finish();
2225    /// let success = Message::from_bytes(&success).unwrap();
2226    /// assert_eq!(success.is_response(), true);
2227    /// ```
2228    fn is_response(&self) -> bool {
2229        self.class().is_response()
2230    }
2231
2232    /// Retrieves the method of the [`Message`].
2233    ///
2234    /// # Examples
2235    ///
2236    /// ```
2237    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2238    /// #     MessageWrite, BINDING};
2239    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2240    /// let message = Message::from_bytes(&message).unwrap();
2241    /// assert_eq!(message.method(), BINDING);
2242    /// ```
2243    fn method(&self) -> Method {
2244        self.get_type().method()
2245    }
2246
2247    /// Returns whether the [`Message`] is of the specified method.
2248    ///
2249    /// # Examples
2250    ///
2251    /// ```
2252    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2253    /// #     Method, MessageWrite, BINDING};
2254    /// let message = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2255    /// let message = Message::from_bytes(&message).unwrap();
2256    /// assert!(message.has_method(BINDING));
2257    /// assert!(!message.has_method(Method::new(0)));
2258    /// ```
2259    fn has_method(&self, method: Method) -> bool {
2260        self.method() == method
2261    }
2262
2263    /// Retrieves the 96-bit transaction ID of the [`Message`].
2264    ///
2265    /// # Examples
2266    ///
2267    /// ```
2268    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2269    /// #     MessageWrite, BINDING, TransactionId};
2270    /// let mtype = MessageType::from_class_method(MessageClass::Request, BINDING);
2271    /// let transaction_id = TransactionId::generate();
2272    /// let message = Message::builder(mtype, transaction_id, MessageWriteVec::new()).finish();
2273    /// let message = Message::from_bytes(&message).unwrap();
2274    /// assert_eq!(message.transaction_id(), transaction_id);
2275    /// ```
2276    fn transaction_id(&self) -> TransactionId {
2277        BigEndian::read_u128(&self.data()[4..]).into()
2278    }
2279
2280    /// Adds MESSAGE_INTEGRITY attribute to a [`Message`] using the provided credentials.
2281    ///
2282    /// # Errors
2283    ///
2284    /// - If a [`MessageIntegrity`] attribute is already present.
2285    /// - If a [`MessageIntegritySha256`] attribute is already present.
2286    /// - If a [`Fingerprint`] attribute is already present.
2287    ///
2288    /// # Examples
2289    ///
2290    /// ```
2291    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2292    /// #     MessageWrite, MessageWriteExt, BINDING, MessageIntegrityCredentials,
2293    /// #     ShortTermCredentials, IntegrityAlgorithm, StunWriteError};
2294    /// # use stun_types::attribute::{Attribute, AttributeStaticType, MessageIntegrity,
2295    /// #     MessageIntegritySha256};
2296    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
2297    /// let credentials = ShortTermCredentials::new("pass".to_owned()).into();
2298    /// assert!(message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1).is_ok());
2299    ///
2300    /// // duplicate MessageIntegrity is an error
2301    /// assert!(matches!(
2302    ///     message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2303    ///     Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE)),
2304    /// ));
2305    ///
2306    /// // both MessageIntegrity, and MessageIntegritySha256 are allowed, however Sha256 must be
2307    /// // after Sha1
2308    /// assert!(message.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256).is_ok());
2309    ///
2310    /// let data = message.finish();
2311    /// let message = Message::from_bytes(&data).unwrap();
2312    /// assert!(message.validate_integrity(&credentials).is_ok());
2313    /// ```
2314    fn add_message_integrity(
2315        &mut self,
2316        credentials: &MessageIntegrityCredentials,
2317        algorithm: IntegrityAlgorithm,
2318    ) -> Result<(), StunWriteError> {
2319        let key = credentials.make_key(algorithm);
2320        self.add_message_integrity_with_key(&key, algorithm)
2321    }
2322
2323    /// Adds MESSAGE_INTEGRITY attribute to a [`Message`] using the provided credential key.
2324    #[tracing::instrument(
2325        name = "message_add_integrity_with_key",
2326        level = "trace",
2327        err,
2328        skip(self),
2329        fields(
2330            msg.transaction = %self.transaction_id(),
2331        )
2332    )]
2333    fn add_message_integrity_with_key(
2334        &mut self,
2335        key: &IntegrityKey,
2336        algorithm: IntegrityAlgorithm,
2337    ) -> Result<(), StunWriteError> {
2338        let mut atypes = [AttributeType::new(0); 3];
2339        let mut i = 0;
2340        atypes[i] = match algorithm {
2341            IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
2342            IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
2343        };
2344        i += 1;
2345        if algorithm == IntegrityAlgorithm::Sha1 {
2346            atypes[i] = MessageIntegritySha256::TYPE;
2347            i += 1;
2348        }
2349        atypes[i] = Fingerprint::TYPE;
2350        i += 1;
2351
2352        match self.has_any_attribute(&atypes[..i]) {
2353            // can't validly add generic attributes after message integrity or fingerprint
2354            Some(MessageIntegrity::TYPE) => {
2355                return Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2356            }
2357            Some(MessageIntegritySha256::TYPE) => {
2358                return Err(StunWriteError::AttributeExists(
2359                    MessageIntegritySha256::TYPE,
2360                ));
2361            }
2362            Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2363            _ => (),
2364        }
2365        match algorithm {
2366            IntegrityAlgorithm::Sha1 => {
2367                check_attribute_can_fit(self, &MessageIntegrity::new([0; 20]))?
2368            }
2369            IntegrityAlgorithm::Sha256 => {
2370                check_attribute_can_fit(self, &MessageIntegritySha256::new(&[0; 32]).unwrap())?
2371            }
2372        };
2373
2374        unsafe { self.add_message_integrity_with_key_unchecked(key, algorithm) };
2375
2376        Ok(())
2377    }
2378
2379    /// Adds MESSAGE_INTEGRITY attribute to a [`Message`] using the provided credential key.
2380    ///
2381    /// # Safety
2382    ///
2383    /// The caller must ensure that:
2384    ///
2385    /// 1. The provided writer has enough room to store the new allocated message integrity
2386    ///    attribute applicable for the relevant algorithm.
2387    /// 2. That another integrity algorithm attribute has not already been added to the message.
2388    /// 3. That the [`Fingerprint`] attribute has not been added to the message.
2389    unsafe fn add_message_integrity_with_key_unchecked(
2390        &mut self,
2391        key: &IntegrityKey,
2392        algorithm: IntegrityAlgorithm,
2393    ) {
2394        // message-integrity is computed using all the data up to (exclusive of) the
2395        // MESSAGE-INTEGRITY but with a length field including the MESSAGE-INTEGRITY attribute...
2396        match algorithm {
2397            IntegrityAlgorithm::Sha1 => {
2398                self.push_attribute_unchecked(&MessageIntegrity::new([0; 20]));
2399                let len = self.len();
2400                let data = self.mut_data();
2401                let integrity = MessageIntegrity::compute(&[&data[..len - 24]], key).unwrap();
2402                data[len - 20..].copy_from_slice(&integrity);
2403            }
2404            IntegrityAlgorithm::Sha256 => {
2405                self.push_attribute_unchecked(&MessageIntegritySha256::new(&[0; 32]).unwrap());
2406                let len = self.len();
2407                let data = self.mut_data();
2408                let integrity = MessageIntegritySha256::compute(&[&data[..len - 36]], key).unwrap();
2409                data[len - 32..].copy_from_slice(&integrity);
2410            }
2411        }
2412    }
2413
2414    /// Adds [`Fingerprint`] attribute to a [`Message`].
2415    ///
2416    /// # Errors
2417    ///
2418    /// - If a [`Fingerprint`] attribute is already present.
2419    ///
2420    /// # Examples
2421    ///
2422    /// ```
2423    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2424    /// #     MessageWriteExt, BINDING};
2425    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
2426    /// assert!(message.add_fingerprint().is_ok());
2427    ///
2428    /// // duplicate FINGERPRINT is an error
2429    /// assert!(message.add_fingerprint().is_err());
2430    /// ```
2431    #[tracing::instrument(
2432        name = "message_add_fingerprint",
2433        level = "trace",
2434        skip(self),
2435        fields(
2436            msg.transaction = %self.transaction_id(),
2437        )
2438    )]
2439    fn add_fingerprint(&mut self) -> Result<(), StunWriteError> {
2440        if self.has_attribute(Fingerprint::TYPE) {
2441            return Err(StunWriteError::AttributeExists(Fingerprint::TYPE));
2442        }
2443
2444        check_attribute_can_fit(self, &Fingerprint::new([0; 4]))?;
2445        unsafe { self.add_fingerprint_unchecked() };
2446
2447        Ok(())
2448    }
2449
2450    /// Adds [`Fingerprint`] attribute to a [`Message`].
2451    ///
2452    /// # Safety
2453    ///
2454    /// The caller must ensure that:
2455    ///
2456    /// 1. The provided writer has enough room to store the new allocated message integrity
2457    ///    attribute applicable for the relevant algorithm.
2458    /// 2. That the [`Fingerprint`] attribute has not been added to the message.
2459    unsafe fn add_fingerprint_unchecked(&mut self) {
2460        // fingerprint is computed using all the data up to (exclusive of) the FINGERPRINT
2461        // but with a length field including the FINGERPRINT attribute...
2462        self.push_attribute_unchecked(&Fingerprint::new([0; 4]));
2463        let len = self.len();
2464        let data = self.mut_data();
2465        let fingerprint = Fingerprint::compute(&[&data[..len - 8]]);
2466        let fingerprint = Fingerprint::new(fingerprint);
2467        fingerprint.write_into(&mut data[len - 8..]).unwrap();
2468    }
2469
2470    /// Add a `Attribute` to this `Message`.
2471    ///
2472    /// # Errors
2473    ///
2474    /// - If attempting to add attributes when [`MessageIntegrity`], [`MessageIntegritySha256`] or
2475    /// [`Fingerprint`] atributes already exist.
2476    ///
2477    /// # Panics
2478    ///
2479    /// - if a [`MessageIntegrity`] or [`MessageIntegritySha256`] attribute is attempted to be
2480    ///   added. Use `Message::add_message_integrity` instead.
2481    /// - if a [`Fingerprint`] attribute is attempted to be added. Use `Message::add_fingerprint`
2482    ///   instead.
2483    ///
2484    /// # Examples
2485    ///
2486    /// Add an `Attribute`.
2487    ///
2488    /// ```
2489    /// # use stun_types::attribute::RawAttribute;
2490    /// # use stun_types::message::{Message, MessageType, MessageClass, MessageWriteVec,
2491    /// #     MessageWriteExt, BINDING};
2492    /// let mut message = Message::builder_request(BINDING, MessageWriteVec::new());
2493    /// let attr = RawAttribute::new(1.into(), &[3]);
2494    /// assert!(message.add_attribute(&attr).is_ok());
2495    /// // Duplicate attributes are allowed, however semantically, the protocol may not allow them.
2496    /// assert!(message.add_attribute(&attr).is_ok());
2497    /// ```
2498    #[tracing::instrument(
2499        name = "message_add_attribute",
2500        level = "trace",
2501        err,
2502        skip(self, attr),
2503        fields(
2504            msg.transaction = %self.transaction_id(),
2505        )
2506    )]
2507    fn add_attribute(&mut self, attr: &dyn AttributeWrite) -> Result<(), StunWriteError> {
2508        let ty = attr.get_type();
2509        match ty {
2510            MessageIntegrity::TYPE => {
2511                panic!("Cannot write MessageIntegrity with `add_attribute`.  Use add_message_integrity() instead");
2512            }
2513            MessageIntegritySha256::TYPE => {
2514                panic!("Cannot write MessageIntegritySha256 with `add_attribute`.  Use add_message_integrity() instead");
2515            }
2516            Fingerprint::TYPE => {
2517                panic!(
2518                    "Cannot write Fingerprint with `add_attribute`.  Use add_fingerprint() instead"
2519                );
2520            }
2521            _ => (),
2522        }
2523        match self.has_any_attribute(&[
2524            MessageIntegrity::TYPE,
2525            MessageIntegritySha256::TYPE,
2526            Fingerprint::TYPE,
2527        ]) {
2528            // can't validly add generic attributes after message integrity or fingerprint
2529            Some(MessageIntegrity::TYPE) => return Err(StunWriteError::MessageIntegrityExists),
2530            Some(MessageIntegritySha256::TYPE) => {
2531                return Err(StunWriteError::MessageIntegrityExists)
2532            }
2533            Some(Fingerprint::TYPE) => return Err(StunWriteError::FingerprintExists),
2534            _ => (),
2535        }
2536        check_attribute_can_fit(self, attr)?;
2537        self.push_attribute_unchecked(attr);
2538        Ok(())
2539    }
2540}
2541
2542impl<T: MessageWrite> MessageWriteExt for T {}
2543
2544/// A [`MessageWrite`] implementation that writes into a `Vec<u8>`.
2545#[derive(Debug, Default)]
2546pub struct MessageWriteVec {
2547    output: Vec<u8>,
2548    attributes: smallvec::SmallVec<[AttributeType; 16]>,
2549}
2550
2551impl MessageWriteVec {
2552    /// Construct a new [`MessageWriteVec`].
2553    pub fn new() -> Self {
2554        Self::default()
2555    }
2556
2557    /// Allocate a new [`MessageWriteVec`] with a preallocated capacity.
2558    pub fn with_capacity(capacity: usize) -> Self {
2559        Self {
2560            output: Vec::with_capacity(capacity),
2561            attributes: Default::default(),
2562        }
2563    }
2564}
2565
2566impl core::ops::Deref for MessageWriteVec {
2567    type Target = Vec<u8>;
2568    fn deref(&self) -> &Self::Target {
2569        &self.output
2570    }
2571}
2572
2573impl core::ops::DerefMut for MessageWriteVec {
2574    fn deref_mut(&mut self) -> &mut Self::Target {
2575        &mut self.output
2576    }
2577}
2578
2579impl MessageWrite for MessageWriteVec {
2580    type Output = Vec<u8>;
2581
2582    fn mut_data(&mut self) -> &mut [u8] {
2583        &mut self.output
2584    }
2585
2586    fn data(&self) -> &[u8] {
2587        &self.output
2588    }
2589
2590    fn len(&self) -> usize {
2591        self.output.len()
2592    }
2593
2594    fn push_data(&mut self, data: &[u8]) {
2595        self.output.extend(data)
2596    }
2597
2598    fn finish(self) -> Self::Output {
2599        self.output
2600    }
2601
2602    fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2603        let offset = self.output.len();
2604        let padded_len = attr.padded_len();
2605        let expected = offset + padded_len;
2606        BigEndian::write_u16(
2607            &mut self.output[2..4],
2608            (expected - MessageHeader::LENGTH) as u16,
2609        );
2610        self.output.resize(expected, 0);
2611        attr.write_into_unchecked(&mut self.output[offset..]);
2612        self.attributes.push(attr.get_type());
2613    }
2614
2615    fn has_attribute(&self, atype: AttributeType) -> bool {
2616        self.attributes.contains(&atype)
2617    }
2618
2619    fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2620        self.attributes
2621            .iter()
2622            .find(|&typ| atypes.contains(typ))
2623            .cloned()
2624    }
2625}
2626
2627/// A [`MessageWrite`] implementation that writes into a mutable slice.
2628#[derive(Debug, Default)]
2629pub struct MessageWriteMutSlice<'a> {
2630    output: &'a mut [u8],
2631    offset: usize,
2632    attributes: smallvec::SmallVec<[AttributeType; 16]>,
2633}
2634
2635impl<'a> MessageWriteMutSlice<'a> {
2636    /// Construct a new [`MessageWriteMutSlice`] using the provided mutbale slice.
2637    pub fn new(data: &'a mut [u8]) -> Self {
2638        Self {
2639            output: data,
2640            offset: 0,
2641            attributes: Default::default(),
2642        }
2643    }
2644}
2645
2646impl core::ops::Deref for MessageWriteMutSlice<'_> {
2647    type Target = [u8];
2648    fn deref(&self) -> &Self::Target {
2649        self.output
2650    }
2651}
2652
2653impl core::ops::DerefMut for MessageWriteMutSlice<'_> {
2654    fn deref_mut(&mut self) -> &mut Self::Target {
2655        self.output
2656    }
2657}
2658
2659impl<'a> MessageWrite for MessageWriteMutSlice<'a> {
2660    type Output = usize;
2661
2662    fn max_size(&self) -> Option<usize> {
2663        Some(self.output.len())
2664    }
2665
2666    fn mut_data(&mut self) -> &mut [u8] {
2667        &mut self.output[..self.offset]
2668    }
2669
2670    fn data(&self) -> &[u8] {
2671        &self.output[..self.offset]
2672    }
2673
2674    fn len(&self) -> usize {
2675        self.offset
2676    }
2677
2678    fn push_data(&mut self, data: &[u8]) {
2679        let len = data.len();
2680        self.output[self.offset..self.offset + len].copy_from_slice(data);
2681        self.offset += len;
2682    }
2683
2684    fn push_attribute_unchecked(&mut self, attr: &dyn AttributeWrite) {
2685        let padded_len = attr.padded_len();
2686        let expected = self.offset + padded_len;
2687        BigEndian::write_u16(
2688            &mut self.output[2..4],
2689            (expected - MessageHeader::LENGTH) as u16,
2690        );
2691        self.attributes.push(attr.get_type());
2692        attr.write_into(&mut self.output[self.offset..self.offset + padded_len])
2693            .unwrap();
2694        self.offset += padded_len;
2695    }
2696
2697    fn finish(self) -> Self::Output {
2698        self.offset
2699    }
2700
2701    fn has_attribute(&self, atype: AttributeType) -> bool {
2702        self.attributes.contains(&atype)
2703    }
2704
2705    fn has_any_attribute(&self, atypes: &[AttributeType]) -> Option<AttributeType> {
2706        self.attributes
2707            .iter()
2708            .find(|&typ| atypes.contains(typ))
2709            .cloned()
2710    }
2711}
2712
2713fn check_attribute_can_fit<O, T: MessageWrite<Output = O> + ?Sized>(
2714    this: &mut T,
2715    attr: &dyn AttributeWrite,
2716) -> Result<usize, StunWriteError> {
2717    let len = attr.padded_len();
2718    let out_data = this.data();
2719    if out_data.len() < MessageHeader::LENGTH {
2720        return Err(StunWriteError::TooSmall {
2721            expected: 20,
2722            actual: out_data.len(),
2723        });
2724    }
2725    let expected = BigEndian::read_u16(&out_data[2..4]) as usize + MessageHeader::LENGTH + len;
2726    if let Some(max) = this.max_size() {
2727        if max < expected {
2728            return Err(StunWriteError::TooSmall {
2729                expected,
2730                actual: max,
2731            });
2732        }
2733    }
2734    Ok(expected)
2735}
2736
2737#[cfg(test)]
2738mod tests {
2739    use alloc::borrow::ToOwned;
2740    use precis_profiles::precis_core::profile::Profile;
2741    use tracing::error;
2742
2743    use super::*;
2744
2745    #[test]
2746    #[should_panic(expected = "Method value is out of range")]
2747    fn method_value_out_of_range() {
2748        let _log = crate::tests::test_init_log();
2749        Method::new(0xf000);
2750    }
2751
2752    #[test]
2753    #[cfg(feature = "std")]
2754    fn method_name() {
2755        let _log = crate::tests::test_init_log();
2756        assert_eq!(BINDING.name(), "BINDING");
2757        let method = Method::new(0x111);
2758        method.add_name("SOME-NAME");
2759        assert_eq!(method.name(), "SOME-NAME");
2760        assert_eq!(Method::new(0x112).name(), "unknown");
2761    }
2762
2763    #[test]
2764    fn msg_type_roundtrip() {
2765        let _log = crate::tests::test_init_log();
2766        /* validate that all methods/classes survive a roundtrip */
2767        for m in 0..0xfff {
2768            let m = Method::new(m);
2769            let classes = vec![
2770                MessageClass::Request,
2771                MessageClass::Indication,
2772                MessageClass::Success,
2773                MessageClass::Error,
2774            ];
2775            for c in classes {
2776                let mtype = MessageType::from_class_method(c, m);
2777                trace!("{mtype}");
2778                assert_eq!(mtype.class(), c);
2779                assert!(mtype.has_class(c));
2780                assert_eq!(mtype.method(), m);
2781                assert!(mtype.has_method(m));
2782                let bytes = mtype.to_bytes();
2783                let ptype = MessageType::from_bytes(&bytes).unwrap();
2784                assert_eq!(mtype, ptype);
2785            }
2786        }
2787    }
2788
2789    #[test]
2790    fn msg_type_not_stun() {
2791        assert!(matches!(
2792            MessageType::from_bytes(&[0xc0, 0x00]),
2793            Err(StunParseError::NotStun)
2794        ));
2795    }
2796
2797    #[test]
2798    fn msg_roundtrip() {
2799        let _log = crate::tests::test_init_log();
2800        /* validate that all methods/classes survive a roundtrip */
2801        for m in (0x009..0x4ff).step_by(0x123) {
2802            let m = Method::new(m);
2803            let classes = vec![
2804                MessageClass::Request,
2805                MessageClass::Indication,
2806                MessageClass::Success,
2807                MessageClass::Error,
2808            ];
2809            for c in classes {
2810                let mtype = MessageType::from_class_method(c, m);
2811                for tid in (0x18..0xff_ffff_ffff_ffff_ffff).step_by(0xfedc_ba98_7654_3210) {
2812                    let mut msg = Message::builder(mtype, tid.into(), MessageWriteVec::default());
2813                    let attr = RawAttribute::new(1.into(), &[3]);
2814                    assert!(msg.add_attribute(&attr).is_ok());
2815                    let data = msg.finish();
2816
2817                    let msg = Message::from_bytes(&data).unwrap();
2818                    let msg_attr = msg.raw_attribute(1.into()).unwrap();
2819                    assert_eq!(msg_attr, attr);
2820                    assert_eq!(msg.get_type(), mtype);
2821                    assert_eq!(msg.transaction_id(), tid.into());
2822                    assert_eq!(msg.as_bytes(), &data);
2823                    assert_eq!(msg.as_ref(), &data);
2824                }
2825            }
2826        }
2827    }
2828
2829    #[test]
2830    fn unknown_attributes() {
2831        let _log = crate::tests::test_init_log();
2832        let src = Message::builder_request(BINDING, MessageWriteVec::default()).finish();
2833        let src = Message::from_bytes(&src).unwrap();
2834        let msg =
2835            Message::unknown_attributes(&src, &[Software::TYPE], MessageWriteVec::new()).finish();
2836        let msg = Message::from_bytes(&msg).unwrap();
2837        assert_eq!(msg.transaction_id(), src.transaction_id());
2838        assert_eq!(msg.class(), MessageClass::Error);
2839        assert!(msg.has_class(MessageClass::Error));
2840        assert!(!msg.has_class(MessageClass::Success));
2841        assert_eq!(msg.method(), src.method());
2842        assert!(msg.has_method(src.method()));
2843        let err = msg.attribute::<ErrorCode>().unwrap();
2844        assert_eq!(err.code(), 420);
2845        let unknown_attrs = msg.attribute::<UnknownAttributes>().unwrap();
2846        assert!(unknown_attrs.has_attribute(Software::TYPE));
2847    }
2848
2849    #[test]
2850    fn bad_request() {
2851        let _log = crate::tests::test_init_log();
2852        let src = Message::builder_request(BINDING, MessageWriteVec::new()).finish();
2853        let src = Message::from_bytes(&src).unwrap();
2854        let msg = Message::bad_request(&src, MessageWriteVec::new());
2855        assert!(msg.has_class(MessageClass::Error));
2856        assert!(!msg.has_class(MessageClass::Success));
2857        assert!(msg.has_method(src.method()));
2858        assert!(!msg.has_method(Method::new(0x111)));
2859        assert!(msg.is_response());
2860        let msg = msg.finish();
2861        let msg = Message::from_bytes(&msg).unwrap();
2862        assert_eq!(msg.transaction_id(), src.transaction_id());
2863        assert_eq!(msg.class(), MessageClass::Error);
2864        assert_eq!(msg.method(), src.method());
2865        let err = msg.attribute::<ErrorCode>().unwrap();
2866        assert_eq!(err.code(), 400);
2867    }
2868
2869    #[test]
2870    fn fingerprint() {
2871        let _log = crate::tests::test_init_log();
2872        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2873        assert!(msg.has_class(MessageClass::Request));
2874        assert!(!msg.has_class(MessageClass::Success));
2875        assert!(msg.has_method(BINDING));
2876        assert!(!msg.has_method(Method::new(0x111)));
2877        let software = Software::new("s").unwrap();
2878        msg.add_attribute(&software).unwrap();
2879        msg.add_fingerprint().unwrap();
2880        let bytes = msg.finish();
2881        // validates the fingerprint of the data when available
2882        let new_msg = Message::from_bytes(&bytes).unwrap();
2883        let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2884        assert_eq!(software.software(), "s");
2885        assert_eq!(offset, 20);
2886        let (offset, _new_fingerprint) =
2887            new_msg.raw_attribute_and_offset(Fingerprint::TYPE).unwrap();
2888        assert_eq!(offset, 28);
2889    }
2890
2891    #[test]
2892    fn integrity() {
2893        let _log = crate::tests::test_init_log();
2894        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2895            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2896            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2897            let software = Software::new("s").unwrap();
2898            msg.add_attribute(&software).unwrap();
2899            msg.add_message_integrity(&credentials, algorithm).unwrap();
2900            let bytes = msg.finish();
2901            // validates the fingerprint of the data when available
2902            let new_msg = Message::from_bytes(&bytes).unwrap();
2903            new_msg.validate_integrity(&credentials).unwrap();
2904            let (offset, software) = new_msg.attribute_and_offset::<Software>().unwrap();
2905            assert_eq!(software.software(), "s");
2906            assert_eq!(offset, 20);
2907        }
2908    }
2909
2910    #[test]
2911    fn write_into_short_destination() {
2912        let _log = crate::tests::test_init_log();
2913        const LEN: usize = MessageHeader::LENGTH + 8;
2914        let mut data = [0; LEN - 1];
2915        let mut msg = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
2916        let software = Software::new("s").unwrap();
2917        assert!(
2918            matches!(msg.add_attribute(&software), Err(StunWriteError::TooSmall { expected, actual }) if expected == LEN && actual == LEN - 1)
2919        );
2920    }
2921
2922    #[test]
2923    fn integrity_key() {
2924        let _log = crate::tests::test_init_log();
2925        let credentials1 = ShortTermCredentials::new("pass1".to_owned());
2926        let key1 =
2927            MessageIntegrityCredentials::from(credentials1).make_key(IntegrityAlgorithm::Sha1);
2928        let credentials2 = ShortTermCredentials::new("pass2".to_owned());
2929        let key2 =
2930            MessageIntegrityCredentials::from(credentials2).make_key(IntegrityAlgorithm::Sha1);
2931        assert_eq!(key1, key1);
2932        assert_eq!(key2, key2);
2933        assert_ne!(key1, key2);
2934    }
2935
2936    #[test]
2937    fn add_duplicate_integrity() {
2938        let _log = crate::tests::test_init_log();
2939        let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2940        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2941        msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
2942            .unwrap();
2943        assert!(matches!(
2944            msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2945            Err(StunWriteError::AttributeExists(MessageIntegrity::TYPE))
2946        ));
2947        msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2948            .unwrap();
2949        assert!(matches!(
2950            msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256),
2951            Err(StunWriteError::AttributeExists(
2952                MessageIntegritySha256::TYPE
2953            ))
2954        ));
2955        let software = Software::new("s").unwrap();
2956        assert!(matches!(
2957            msg.add_attribute(&software),
2958            Err(StunWriteError::MessageIntegrityExists)
2959        ));
2960    }
2961
2962    #[test]
2963    fn add_sha1_integrity_after_sha256() {
2964        let _log = crate::tests::test_init_log();
2965        let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2966        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2967        msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
2968            .unwrap();
2969        assert!(matches!(
2970            msg.add_message_integrity(&credentials, IntegrityAlgorithm::Sha1),
2971            Err(StunWriteError::AttributeExists(
2972                MessageIntegritySha256::TYPE
2973            ))
2974        ));
2975    }
2976
2977    #[test]
2978    fn add_attribute_after_integrity() {
2979        let _log = crate::tests::test_init_log();
2980        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2981            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2982            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2983            msg.add_message_integrity(&credentials, algorithm).unwrap();
2984            let software = Software::new("s").unwrap();
2985            assert!(matches!(
2986                msg.add_attribute(&software),
2987                Err(StunWriteError::MessageIntegrityExists)
2988            ));
2989        }
2990    }
2991
2992    #[test]
2993    fn add_raw_attribute_after_integrity() {
2994        let _log = crate::tests::test_init_log();
2995        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
2996            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
2997            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
2998            msg.add_message_integrity(&credentials, algorithm).unwrap();
2999            let software = Software::new("s").unwrap();
3000            let raw = software.to_raw();
3001            assert!(matches!(
3002                msg.add_attribute(&raw),
3003                Err(StunWriteError::MessageIntegrityExists)
3004            ));
3005        }
3006    }
3007
3008    #[test]
3009    fn add_integrity_after_fingerprint() {
3010        let _log = crate::tests::test_init_log();
3011        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
3012            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
3013            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3014            msg.add_fingerprint().unwrap();
3015            assert!(matches!(
3016                msg.add_message_integrity(&credentials, algorithm),
3017                Err(StunWriteError::FingerprintExists)
3018            ));
3019        }
3020    }
3021
3022    #[test]
3023    fn duplicate_fingerprint() {
3024        let _log = crate::tests::test_init_log();
3025        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3026        msg.add_fingerprint().unwrap();
3027        assert!(matches!(
3028            msg.add_fingerprint(),
3029            Err(StunWriteError::AttributeExists(Fingerprint::TYPE))
3030        ));
3031    }
3032
3033    #[test]
3034    fn parse_invalid_fingerprint() {
3035        let _log = crate::tests::test_init_log();
3036        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3037        msg.add_fingerprint().unwrap();
3038        let mut bytes = msg.finish();
3039        bytes[24] = 0x80;
3040        bytes[25] = 0x80;
3041        bytes[26] = 0x80;
3042        bytes[27] = 0x80;
3043        assert!(matches!(
3044            Message::from_bytes(&bytes),
3045            Err(StunParseError::FingerprintMismatch)
3046        ));
3047    }
3048
3049    #[test]
3050    fn parse_wrong_magic() {
3051        let _log = crate::tests::test_init_log();
3052        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3053        msg.add_fingerprint().unwrap();
3054        let mut bytes = msg.finish();
3055        bytes[4] = 0x80;
3056        assert!(matches!(
3057            Message::from_bytes(&bytes),
3058            Err(StunParseError::NotStun)
3059        ));
3060    }
3061
3062    #[test]
3063    fn parse_attribute_after_integrity() {
3064        let _log = crate::tests::test_init_log();
3065        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
3066            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
3067            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3068            msg.add_message_integrity(&credentials, algorithm).unwrap();
3069            let mut bytes = msg.finish();
3070            let software = Software::new("s").unwrap();
3071            let software_bytes = RawAttribute::from(&software).to_bytes();
3072            let software_len = software_bytes.len();
3073            bytes.extend(software_bytes);
3074            bytes[3] += software_len as u8;
3075            let msg = Message::from_bytes(&bytes).unwrap();
3076            assert!(msg.raw_attribute(Software::TYPE).is_none());
3077        }
3078    }
3079
3080    #[test]
3081    fn parse_duplicate_integrity_after_integrity() {
3082        let _log = crate::tests::test_init_log();
3083        for algorithm in [IntegrityAlgorithm::Sha1, IntegrityAlgorithm::Sha256] {
3084            let credentials = ShortTermCredentials::new("secret".to_owned()).into();
3085            let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3086            msg.add_message_integrity(&credentials, algorithm).unwrap();
3087            // duplicate integrity attribute. Don't do this in real code!
3088            unsafe {
3089                msg.add_message_integrity_with_key_unchecked(
3090                    &credentials.make_key(IntegrityAlgorithm::Sha1),
3091                    algorithm,
3092                )
3093            };
3094            let bytes = msg.finish();
3095            let integrity_type = match algorithm {
3096                IntegrityAlgorithm::Sha1 => MessageIntegrity::TYPE,
3097                IntegrityAlgorithm::Sha256 => MessageIntegritySha256::TYPE,
3098            };
3099            let msg = Message::from_bytes(&bytes).unwrap();
3100            msg.nth_raw_attribute(integrity_type, 0).unwrap();
3101            assert!(msg.nth_raw_attribute(integrity_type, 1).is_none());
3102        }
3103    }
3104
3105    #[test]
3106    fn parse_attribute_after_fingerprint() {
3107        let _log = crate::tests::test_init_log();
3108        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3109        msg.add_fingerprint().unwrap();
3110        let mut bytes = msg.finish();
3111        let software = Software::new("s").unwrap();
3112        let software_bytes = RawAttribute::from(&software).to_bytes();
3113        let software_len = software_bytes.len();
3114        bytes.extend(software_bytes);
3115        bytes[3] += software_len as u8;
3116        let msg = Message::from_bytes(&bytes).unwrap();
3117        assert!(msg.raw_attribute(Fingerprint::TYPE).is_some());
3118        assert!(msg.raw_attribute(Software::TYPE).is_none());
3119    }
3120
3121    #[test]
3122    fn parse_duplicate_fingerprint_after_fingerprint() {
3123        let _log = crate::tests::test_init_log();
3124        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3125        msg.add_fingerprint().unwrap();
3126        unsafe { msg.add_fingerprint_unchecked() };
3127        let bytes = msg.finish();
3128        let msg = Message::from_bytes(&bytes).unwrap();
3129        assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 0).is_some());
3130        assert!(msg.nth_raw_attribute(Fingerprint::TYPE, 1).is_none());
3131    }
3132
3133    #[test]
3134    fn add_attribute_after_fingerprint() {
3135        let _log = crate::tests::test_init_log();
3136        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3137        msg.add_fingerprint().unwrap();
3138        let software = Software::new("s").unwrap();
3139        assert!(matches!(
3140            msg.add_attribute(&software),
3141            Err(StunWriteError::FingerprintExists)
3142        ));
3143    }
3144
3145    #[test]
3146    fn add_raw_attribute_after_fingerprint() {
3147        let _log = crate::tests::test_init_log();
3148        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3149        msg.add_fingerprint().unwrap();
3150        let software = Software::new("s").unwrap();
3151        let raw = software.to_raw();
3152        assert!(matches!(
3153            msg.add_attribute(&raw),
3154            Err(StunWriteError::FingerprintExists)
3155        ));
3156    }
3157
3158    #[test]
3159    fn parse_truncated_message_header() {
3160        let _log = crate::tests::test_init_log();
3161        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3162        msg.add_fingerprint().unwrap();
3163        let bytes = msg.finish();
3164        assert!(matches!(
3165            Message::from_bytes(&bytes[..8]),
3166            Err(StunParseError::Truncated {
3167                expected: 20,
3168                actual: 8
3169            })
3170        ));
3171    }
3172
3173    #[test]
3174    fn parse_truncated_message_header_prefix() {
3175        let _log = crate::tests::test_init_log();
3176        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3177        msg.add_fingerprint().unwrap();
3178        let bytes = msg.finish();
3179        // any prefix of a STUN message header may be the start of a STUN message.
3180        for len in 0..MessageHeader::LENGTH {
3181            assert!(matches!(
3182                MessageHeader::from_bytes(&bytes[..len]),
3183                Err(StunParseError::Truncated {
3184                    expected: 20,
3185                    actual,
3186                }) if actual == len
3187            ));
3188        }
3189        assert!(MessageHeader::from_bytes(&bytes[..MessageHeader::LENGTH]).is_ok());
3190    }
3191
3192    #[test]
3193    fn parse_truncated_message_header_not_stun() {
3194        let _log = crate::tests::test_init_log();
3195        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3196        msg.add_fingerprint().unwrap();
3197        let bytes = msg.finish();
3198        for len in 1..=MessageHeader::LENGTH {
3199            // the two most significant bits of a STUN message are always zero.
3200            for bit in [0x40, 0x80] {
3201                let mut data = bytes[..len].to_vec();
3202                data[0] |= bit;
3203                assert!(matches!(
3204                    MessageHeader::from_bytes(&data),
3205                    Err(StunParseError::NotStun)
3206                ));
3207                assert!(matches!(
3208                    Message::from_bytes(&data),
3209                    Err(StunParseError::NotStun)
3210                ));
3211            }
3212            // any available bytes of the magic cookie must match.
3213            for i in 4..len.min(8) {
3214                let mut data = bytes[..len].to_vec();
3215                data[i] ^= 0xff;
3216                assert!(matches!(
3217                    MessageHeader::from_bytes(&data),
3218                    Err(StunParseError::NotStun)
3219                ));
3220                assert!(matches!(
3221                    Message::from_bytes(&data),
3222                    Err(StunParseError::NotStun)
3223                ));
3224            }
3225        }
3226    }
3227
3228    #[test]
3229    fn parse_truncated_message() {
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 bytes = msg.finish();
3234        assert!(matches!(
3235            Message::from_bytes(&bytes[..24]),
3236            Err(StunParseError::Truncated {
3237                expected: 28,
3238                actual: 24
3239            })
3240        ));
3241    }
3242
3243    #[test]
3244    fn parse_truncated_message_attribute() {
3245        let _log = crate::tests::test_init_log();
3246        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3247        msg.add_fingerprint().unwrap();
3248        let mut bytes = msg.finish();
3249        // rewrite message header to support the truncated length, but not the attribute.
3250        bytes[3] = 4;
3251        assert!(matches!(
3252            Message::from_bytes(&bytes[..24]),
3253            Err(StunParseError::Truncated {
3254                expected: 28,
3255                actual: 24
3256            })
3257        ));
3258    }
3259
3260    #[test]
3261    fn parse_attribute_extends_past_message_end() {
3262        let _log = crate::tests::test_init_log();
3263        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3264        msg.add_attribute(&Software::new("a").unwrap()).unwrap();
3265        msg[23] += 1;
3266        let mut bytes = msg.finish();
3267        bytes[3] -= 1;
3268        error!("{bytes:x?}");
3269        error!("{:?}", Message::from_bytes(&bytes[..27]));
3270        assert!(matches!(
3271            Message::from_bytes(&bytes[..27]),
3272            Err(StunParseError::Truncated {
3273                expected: 28,
3274                actual: 27
3275            })
3276        ));
3277    }
3278
3279    #[test]
3280    fn valid_attributes() {
3281        let _log = crate::tests::test_init_log();
3282        let mut src = Message::builder_request(BINDING, MessageWriteVec::new());
3283        let username = Username::new("123").unwrap();
3284        src.add_attribute(&username).unwrap();
3285        let nonce = Nonce::new("nonce").unwrap();
3286        src.add_attribute(&nonce).unwrap();
3287        assert!(!src.has_attribute(Fingerprint::TYPE));
3288        assert!(src.has_attribute(Nonce::TYPE));
3289        let src = src.finish();
3290        let src = Message::from_bytes(&src).unwrap();
3291        assert!(!src.has_attribute(Fingerprint::TYPE));
3292        assert!(src.has_attribute(Nonce::TYPE));
3293
3294        // success case
3295        let res = Message::check_attribute_types(
3296            &src,
3297            &[Username::TYPE, Nonce::TYPE],
3298            &[Username::TYPE],
3299            MessageWriteVec::new(),
3300        );
3301        assert!(res.is_none());
3302
3303        // fingerprint required but not present
3304        let res = Message::check_attribute_types(
3305            &src,
3306            &[Username::TYPE, Nonce::TYPE],
3307            &[Fingerprint::TYPE],
3308            MessageWriteVec::new(),
3309        );
3310        assert!(res.is_some());
3311        let res = res.unwrap();
3312        let res = res.finish();
3313        let res = Message::from_bytes(&res).unwrap();
3314        assert!(res.has_class(MessageClass::Error));
3315        assert!(res.has_method(src.method()));
3316        let err = res.attribute::<ErrorCode>().unwrap();
3317        assert_eq!(err.code(), 400);
3318
3319        // nonce unsupported
3320        let res =
3321            Message::check_attribute_types(&src, &[Username::TYPE], &[], MessageWriteVec::new());
3322        assert!(res.is_some());
3323        let res = res.unwrap();
3324        let data = res.finish();
3325        let res = Message::from_bytes(&data).unwrap();
3326        assert!(res.has_class(MessageClass::Error));
3327        assert!(res.has_method(src.method()));
3328        let err = res.attribute::<ErrorCode>().unwrap();
3329        assert_eq!(err.code(), 420);
3330        let unknown = res.attribute::<UnknownAttributes>().unwrap();
3331        assert!(unknown.has_attribute(Nonce::TYPE));
3332    }
3333
3334    #[test]
3335    fn attributes_iter_with_short_data() {
3336        let _log = crate::tests::test_init_log();
3337        assert_eq!(
3338            MessageAttributesIter::new(&[0x0, 0x1, 0x2, 0x3, 0x4]).next(),
3339            None
3340        );
3341        assert_eq!(
3342            MessageAttributesIter::new(&[
3343                0x0, 0x1, 0x2, 0x3, 0x21, 0x12, 0xa4, 0x42, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
3344                0x10, 0x11, 0x12, 0x13, 0x14,
3345            ])
3346            .next(),
3347            None
3348        );
3349    }
3350
3351    #[test]
3352    fn attributes_iter_software_after_fingerprint_ignored() {
3353        let _log = crate::tests::test_init_log();
3354        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3355        msg.add_fingerprint().unwrap();
3356        let mut bytes = msg.finish();
3357        let software = Software::new("s").unwrap();
3358        let software_bytes = RawAttribute::from(&software).to_bytes();
3359        let software_len = software_bytes.len();
3360        bytes.extend(software_bytes);
3361        bytes[3] += software_len as u8;
3362        let mut it = MessageAttributesIter::new(&bytes);
3363        let (_offset, fingerprint) = it.next().unwrap();
3364        assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
3365        assert_eq!(it.next(), None);
3366    }
3367
3368    #[test]
3369    fn attributes_iter_message_integrities_fingerprint() {
3370        let _log = crate::tests::test_init_log();
3371        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3372        let credentials = ShortTermCredentials::new("pass".to_owned());
3373        msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
3374            .unwrap();
3375        msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
3376            .unwrap();
3377        msg.add_fingerprint().unwrap();
3378        let mut bytes = msg.finish();
3379        let software = Software::new("s").unwrap();
3380        let software_bytes = RawAttribute::from(&software).to_bytes();
3381        let software_len = software_bytes.len();
3382        bytes.extend(software_bytes);
3383        bytes[3] += software_len as u8;
3384        let mut it = MessageAttributesIter::new(&bytes);
3385        assert_eq!(it.next().unwrap().1.get_type(), MessageIntegrity::TYPE);
3386        assert_eq!(
3387            it.next().unwrap().1.get_type(),
3388            MessageIntegritySha256::TYPE
3389        );
3390        assert_eq!(it.next().unwrap().1.get_type(), Fingerprint::TYPE);
3391        assert_eq!(it.next(), None);
3392    }
3393
3394    #[test]
3395    fn message_parse_multiple_integrities_fingerprint() {
3396        let _log = crate::tests::test_init_log();
3397        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3398        let credentials = ShortTermCredentials::new("pass".to_owned());
3399        msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha1)
3400            .unwrap();
3401        msg.add_message_integrity(&credentials.clone().into(), IntegrityAlgorithm::Sha256)
3402            .unwrap();
3403        msg.add_fingerprint().unwrap();
3404        let key = credentials.make_key();
3405        let bytes = msg.finish();
3406        let msg = Message::from_bytes(&bytes).unwrap();
3407        assert!(msg.has_attribute(MessageIntegrity::TYPE));
3408        assert!(msg.has_attribute(MessageIntegritySha256::TYPE));
3409        assert!(!msg.has_attribute(Software::TYPE));
3410        assert_eq!(
3411            msg.validate_integrity(&credentials.clone().into()).unwrap(),
3412            IntegrityAlgorithm::Sha256
3413        );
3414        assert_eq!(
3415            msg.validate_integrity_with_key(&key).unwrap(),
3416            IntegrityAlgorithm::Sha256
3417        );
3418    }
3419
3420    #[test]
3421    fn validate_integrity_missing_attribute() {
3422        let _log = crate::tests::test_init_log();
3423        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3424        msg.add_fingerprint().unwrap();
3425        let credentials = ShortTermCredentials::new("pass".to_owned());
3426        let key = credentials.make_key();
3427        let bytes = msg.finish();
3428        let msg = Message::from_bytes(&bytes).unwrap();
3429        assert!(matches!(
3430            msg.validate_integrity(&credentials.clone().into()),
3431            Err(ValidateError::Parse(StunParseError::MissingAttribute(
3432                MessageIntegrity::TYPE
3433            )))
3434        ));
3435        assert!(matches!(
3436            msg.validate_integrity_with_key(&key),
3437            Err(ValidateError::Parse(StunParseError::MissingAttribute(
3438                MessageIntegrity::TYPE
3439            )))
3440        ));
3441    }
3442
3443    #[test]
3444    fn attributes_iter_fingerprint_after_fingerprint_ignored() {
3445        let _log = crate::tests::test_init_log();
3446        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3447        msg.add_fingerprint().unwrap();
3448        let mut bytes = msg.finish();
3449        let fingerprint = Fingerprint::new([bytes[bytes.len() - 1].wrapping_sub(1); 4]);
3450        let fingerprint_bytes = RawAttribute::from(&fingerprint).to_bytes();
3451        let fingerprint_len = fingerprint_bytes.len();
3452        bytes.extend(fingerprint_bytes);
3453        bytes[3] += fingerprint_len as u8;
3454        let mut it = MessageAttributesIter::new(&bytes);
3455        let (_offset, fingerprint) = it.next().unwrap();
3456        assert_eq!(fingerprint.get_type(), Fingerprint::TYPE);
3457        assert_eq!(it.next(), None);
3458    }
3459
3460    #[test]
3461    fn write_vec_state() {
3462        let _log = crate::tests::test_init_log();
3463        let mut src = Message::builder_request(BINDING, MessageWriteVec::with_capacity(0x10));
3464        assert_eq!(src.len(), 20);
3465        assert_eq!(src[4], 0x21);
3466        let username = Username::new("123").unwrap();
3467        src.add_attribute(&username).unwrap();
3468        let nonce = Nonce::new("nonce").unwrap();
3469        src.add_attribute(&nonce).unwrap();
3470
3471        assert!(src.has_attribute(Username::TYPE));
3472        assert!(src.has_attribute(Nonce::TYPE));
3473        assert_eq!(
3474            src.has_any_attribute(&[Username::TYPE, Nonce::TYPE]),
3475            Some(Username::TYPE)
3476        );
3477        assert_eq!(
3478            src.has_any_attribute(&[Nonce::TYPE, Username::TYPE]),
3479            Some(Username::TYPE)
3480        );
3481        assert!(src.has_class(MessageClass::Request));
3482        assert!(!src.is_response());
3483        assert!(src.has_method(BINDING));
3484        assert!(src.get_type().has_method(BINDING));
3485        assert!(src.get_type().has_class(MessageClass::Request));
3486        assert!(!src.has_method(Method::new(0x111)));
3487        assert!(!src.get_type().has_method(Method::new(0x111)));
3488        assert!(!src.get_type().has_class(MessageClass::Error));
3489    }
3490
3491    #[test]
3492    fn write_mut_slice_success() {
3493        let _log = crate::tests::test_init_log();
3494        let mut data = [0; 64];
3495        let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3496        assert_eq!(src.len(), 20);
3497        assert_eq!(src[4], 0x21);
3498        let username = Username::new("123").unwrap();
3499        src.add_attribute(&username).unwrap();
3500        let nonce = Nonce::new("nonce").unwrap();
3501        src.add_attribute(&nonce).unwrap();
3502        assert!(src.has_attribute(Username::TYPE));
3503        assert_eq!(
3504            src.has_any_attribute(&[Username::TYPE]),
3505            Some(Username::TYPE)
3506        );
3507        assert!(!src.has_attribute(Software::TYPE));
3508        assert_eq!(src.has_any_attribute(&[Realm::TYPE]), None);
3509        assert_eq!(src.mut_data().len(), src.len());
3510        assert_eq!(src.finish(), 40);
3511        let msg = Message::from_bytes(&data[..40]).unwrap();
3512        let u2 = msg.attribute::<Username>().unwrap();
3513        assert_eq!(u2.username(), "123");
3514        let n2 = msg.attribute::<Nonce>().unwrap();
3515        assert_eq!(n2.nonce(), "nonce");
3516    }
3517
3518    #[test]
3519    fn write_mut_slice_too_short() {
3520        let _log = crate::tests::test_init_log();
3521        let mut data = [0; 27];
3522        let mut src = Message::builder_request(BINDING, MessageWriteMutSlice::new(&mut data));
3523        assert!(matches!(
3524            src.add_attribute(&Username::new("123").unwrap()),
3525            Err(StunWriteError::TooSmall {
3526                expected: 28,
3527                actual: 27
3528            })
3529        ));
3530    }
3531
3532    #[test]
3533    #[should_panic(expected = "created from a non-request message")]
3534    fn builder_success_panic() {
3535        let _log = crate::tests::test_init_log();
3536        let msg = Message::builder(
3537            MessageType::from_class_method(MessageClass::Indication, BINDING),
3538            TransactionId::generate(),
3539            MessageWriteVec::new(),
3540        )
3541        .finish();
3542        let msg = Message::from_bytes(&msg).unwrap();
3543        let _builder = Message::builder_success(&msg, MessageWriteVec::new());
3544    }
3545
3546    #[test]
3547    #[should_panic(expected = "created from a non-request message")]
3548    fn builder_error_panic() {
3549        let _log = crate::tests::test_init_log();
3550        let msg = Message::builder(
3551            MessageType::from_class_method(MessageClass::Indication, BINDING),
3552            TransactionId::generate(),
3553            MessageWriteVec::new(),
3554        )
3555        .finish();
3556        let msg = Message::from_bytes(&msg).unwrap();
3557        let _builder = Message::builder_error(&msg, MessageWriteVec::new());
3558    }
3559
3560    #[test]
3561    #[should_panic(expected = "Use add_message_integrity() instead")]
3562    fn builder_add_attribute_integrity_panic() {
3563        let _log = crate::tests::test_init_log();
3564        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3565        let hmac = [2; 20];
3566        let integrity = MessageIntegrity::new(hmac);
3567        msg.add_attribute(&integrity).unwrap();
3568    }
3569
3570    #[test]
3571    #[should_panic(expected = "Use add_message_integrity() instead")]
3572    fn builder_add_raw_attribute_integrity_panic() {
3573        let _log = crate::tests::test_init_log();
3574        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3575        let hmac = [2; 20];
3576        let integrity = MessageIntegrity::new(hmac);
3577        let raw = integrity.to_raw();
3578        msg.add_attribute(&raw).unwrap();
3579    }
3580
3581    #[test]
3582    #[should_panic(expected = "Use add_message_integrity() instead")]
3583    fn builder_add_attribute_integrity_sha256_panic() {
3584        let _log = crate::tests::test_init_log();
3585        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3586        let hmac = [2; 16];
3587        let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3588        msg.add_attribute(&integrity).unwrap();
3589    }
3590
3591    #[test]
3592    #[should_panic(expected = "Use add_message_integrity() instead")]
3593    fn builder_add_raw_attribute_integrity_sha256_panic() {
3594        let _log = crate::tests::test_init_log();
3595        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3596        let hmac = [2; 16];
3597        let integrity = MessageIntegritySha256::new(&hmac).unwrap();
3598        let raw = integrity.to_raw();
3599        msg.add_attribute(&raw).unwrap();
3600    }
3601
3602    #[test]
3603    #[should_panic(expected = "Use add_fingerprint() instead")]
3604    fn builder_add_attribute_fingerprint_panic() {
3605        let _log = crate::tests::test_init_log();
3606        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3607        let fingerprint = [2; 4];
3608        let fingerprint = Fingerprint::new(fingerprint);
3609        msg.add_attribute(&fingerprint).unwrap();
3610    }
3611
3612    #[test]
3613    #[should_panic(expected = "Use add_fingerprint() instead")]
3614    fn builder_add_raw_attribute_fingerprint_panic() {
3615        let _log = crate::tests::test_init_log();
3616        let mut msg = Message::builder_request(BINDING, MessageWriteVec::new());
3617        let fingerprint = [2; 4];
3618        let fingerprint = Fingerprint::new(fingerprint);
3619        let raw = fingerprint.to_raw();
3620        msg.add_attribute(&raw).unwrap();
3621    }
3622
3623    #[test]
3624    fn rfc5769_vector1() {
3625        let _log = crate::tests::test_init_log();
3626        // https://tools.ietf.org/html/rfc5769#section-2.1
3627        let data = vec![
3628            0x00, 0x01, 0x00, 0x58, // Request type message length
3629            0x21, 0x12, 0xa4, 0x42, // Magic cookie
3630            0xb7, 0xe7, 0xa7, 0x01, // }
3631            0xbc, 0x34, 0xd6, 0x86, // } Transaction ID
3632            0xfa, 0x87, 0xdf, 0xae, // }
3633            0x80, 0x22, 0x00, 0x10, // SOFTWARE header
3634            0x53, 0x54, 0x55, 0x4e, //   }
3635            0x20, 0x74, 0x65, 0x73, //   }  User-agent...
3636            0x74, 0x20, 0x63, 0x6c, //   }  ...name
3637            0x69, 0x65, 0x6e, 0x74, //   }
3638            0x00, 0x24, 0x00, 0x04, // PRIORITY header
3639            0x6e, 0x00, 0x01, 0xff, //   PRIORITY value
3640            0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED header
3641            0x93, 0x2f, 0xf9, 0xb1, //   Pseudo random number
3642            0x51, 0x26, 0x3b, 0x36, //   ... for tie breaker
3643            0x00, 0x06, 0x00, 0x09, // USERNAME header
3644            0x65, 0x76, 0x74, 0x6a, //   Username value
3645            0x3a, 0x68, 0x36, 0x76, //   (9 bytes)
3646            0x59, 0x20, 0x20, 0x20, //   (3 bytes padding)
3647            0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY header
3648            0x9a, 0xea, 0xa7, 0x0c, //   }
3649            0xbf, 0xd8, 0xcb, 0x56, //   }
3650            0x78, 0x1e, 0xf2, 0xb5, //   } HMAC-SHA1 fingerprint
3651            0xb2, 0xd3, 0xf2, 0x49, //   }
3652            0xc1, 0xb5, 0x71, 0xa2, //   }
3653            0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
3654            0xe5, 0x7a, 0x3b, 0xcf, //   CRC32 fingerprint
3655        ];
3656        let msg = Message::from_bytes(&data).unwrap();
3657        assert!(msg.has_class(MessageClass::Request));
3658        assert!(msg.has_method(BINDING));
3659        assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3660
3661        let mut builder = Message::builder(
3662            MessageType::from_class_method(MessageClass::Request, BINDING),
3663            msg.transaction_id(),
3664            MessageWriteVec::new(),
3665        );
3666
3667        // SOFTWARE
3668        assert!(msg.has_attribute(Software::TYPE));
3669        let raw = msg.raw_attribute(Software::TYPE).unwrap();
3670        assert!(Software::try_from(&raw).is_ok());
3671        let software = Software::try_from(&raw).unwrap();
3672        assert_eq!(software.software(), "STUN test client");
3673        builder.add_attribute(&software).unwrap();
3674
3675        // PRIORITY handled elswhere
3676        builder
3677            .add_attribute(&RawAttribute::new(0x24.into(), &[0x6e, 0x00, 0x01, 0xff]))
3678            .unwrap();
3679
3680        // ICE-CONTROLLED handled elswhere
3681        builder
3682            .add_attribute(&RawAttribute::new(
3683                0x8029.into(),
3684                &[0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36],
3685            ))
3686            .unwrap();
3687
3688        // USERNAME
3689        assert!(msg.has_attribute(Username::TYPE));
3690        let raw = msg.raw_attribute(Username::TYPE).unwrap();
3691        assert!(Username::try_from(&raw).is_ok());
3692        let username = Username::try_from(&raw).unwrap();
3693        assert_eq!(username.username(), "evtj:h6vY");
3694        builder.add_attribute(&username).unwrap();
3695
3696        // MESSAGE_INTEGRITY
3697        let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3698            password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3699        });
3700        assert!(matches!(
3701            msg.validate_integrity(&credentials),
3702            Ok(IntegrityAlgorithm::Sha1)
3703        ));
3704        builder
3705            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3706            .unwrap();
3707
3708        // FINGERPRINT is checked by Message::from_bytes() when present
3709        assert!(msg.has_attribute(Fingerprint::TYPE));
3710        builder.add_fingerprint().unwrap();
3711
3712        // assert that we produce the same output as we parsed in this case
3713        let mut msg_data = builder.finish();
3714        // match the padding bytes with the original
3715        msg_data[73] = 0x20;
3716        msg_data[74] = 0x20;
3717        msg_data[75] = 0x20;
3718        // as a result of the padding difference, the message integrity and fingerpinrt values will
3719        // be different
3720        assert_eq!(msg_data[..80], data[..80]);
3721    }
3722
3723    #[test]
3724    fn rfc5769_vector2() {
3725        let _log = crate::tests::test_init_log();
3726        // https://tools.ietf.org/html/rfc5769#section-2.2
3727        let data = vec![
3728            0x01, 0x01, 0x00, 0x3c, // Response type message length
3729            0x21, 0x12, 0xa4, 0x42, // Magic cookie
3730            0xb7, 0xe7, 0xa7, 0x01, // }
3731            0xbc, 0x34, 0xd6, 0x86, // }  Transaction ID
3732            0xfa, 0x87, 0xdf, 0xae, // }
3733            0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header
3734            0x74, 0x65, 0x73, 0x74, //   }
3735            0x20, 0x76, 0x65, 0x63, //   }  UTF-8 server name
3736            0x74, 0x6f, 0x72, 0x20, //   }
3737            0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header
3738            0x00, 0x01, 0xa1, 0x47, //   Address family (IPv4) and xor'd mapped port number
3739            0xe1, 0x12, 0xa6, 0x43, //   Xor'd mapped IPv4 address
3740            0x00, 0x08, 0x00, 0x14, //   MESSAGE-INTEGRITY attribute header
3741            0x2b, 0x91, 0xf5, 0x99, // }
3742            0xfd, 0x9e, 0x90, 0xc3, // }
3743            0x8c, 0x74, 0x89, 0xf9, // }  HMAC-SHA1 fingerprint
3744            0x2a, 0xf9, 0xba, 0x53, // }
3745            0xf0, 0x6b, 0xe7, 0xd7, // }
3746            0x80, 0x28, 0x00, 0x04, //  FINGERPRINT attribute header
3747            0xc0, 0x7d, 0x4c, 0x96, //  CRC32 fingerprint
3748        ];
3749
3750        let msg = Message::from_bytes(&data).unwrap();
3751        assert!(msg.has_class(MessageClass::Success));
3752        assert!(msg.has_method(BINDING));
3753        assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3754        let mut builder = Message::builder(
3755            MessageType::from_class_method(MessageClass::Success, BINDING),
3756            msg.transaction_id(),
3757            MessageWriteVec::new(),
3758        );
3759
3760        // SOFTWARE
3761        assert!(msg.has_attribute(Software::TYPE));
3762        let raw = msg.raw_attribute(Software::TYPE).unwrap();
3763        assert!(Software::try_from(&raw).is_ok());
3764        let software = Software::try_from(&raw).unwrap();
3765        assert_eq!(software.software(), "test vector");
3766        builder.add_attribute(&software).unwrap();
3767
3768        // XOR_MAPPED_ADDRESS
3769        assert!(msg.has_attribute(XorMappedAddress::TYPE));
3770        let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3771        assert!(XorMappedAddress::try_from(&raw).is_ok());
3772        let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3773        assert_eq!(
3774            xor_mapped_addres.addr(msg.transaction_id()),
3775            "192.0.2.1:32853".parse().unwrap()
3776        );
3777        builder.add_attribute(&xor_mapped_addres).unwrap();
3778
3779        // MESSAGE_INTEGRITY
3780        let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3781            password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3782        });
3783        let ret = msg.validate_integrity(&credentials);
3784        warn!("{:?}", ret);
3785        assert!(matches!(ret, Ok(IntegrityAlgorithm::Sha1)));
3786        builder
3787            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3788            .unwrap();
3789
3790        // FINGERPRINT is checked by Message::from_bytes() when present
3791        assert!(msg.has_attribute(Fingerprint::TYPE));
3792        builder.add_fingerprint().unwrap();
3793
3794        // assert that we produce the same output as we parsed in this case
3795        let mut msg_data = builder.finish();
3796        // match the padding bytes with the original
3797        msg_data[35] = 0x20;
3798        assert_eq!(msg_data[..52], data[..52]);
3799    }
3800
3801    #[test]
3802    fn rfc5769_vector3() {
3803        let _log = crate::tests::test_init_log();
3804        // https://tools.ietf.org/html/rfc5769#section-2.3
3805        let data = vec![
3806            0x01, 0x01, 0x00, 0x48, // Response type and message length
3807            0x21, 0x12, 0xa4, 0x42, // Magic cookie
3808            0xb7, 0xe7, 0xa7, 0x01, // }
3809            0xbc, 0x34, 0xd6, 0x86, // }  Transaction ID
3810            0xfa, 0x87, 0xdf, 0xae, // }
3811            0x80, 0x22, 0x00, 0x0b, //    SOFTWARE attribute header
3812            0x74, 0x65, 0x73, 0x74, // }
3813            0x20, 0x76, 0x65, 0x63, // }  UTF-8 server name
3814            0x74, 0x6f, 0x72, 0x20, // }
3815            0x00, 0x20, 0x00, 0x14, //    XOR-MAPPED-ADDRESS attribute header
3816            0x00, 0x02, 0xa1, 0x47, //    Address family (IPv6) and xor'd mapped port number
3817            0x01, 0x13, 0xa9, 0xfa, // }
3818            0xa5, 0xd3, 0xf1, 0x79, // }  Xor'd mapped IPv6 address
3819            0xbc, 0x25, 0xf4, 0xb5, // }
3820            0xbe, 0xd2, 0xb9, 0xd9, // }
3821            0x00, 0x08, 0x00, 0x14, //    MESSAGE-INTEGRITY attribute header
3822            0xa3, 0x82, 0x95, 0x4e, // }
3823            0x4b, 0xe6, 0x7b, 0xf1, // }
3824            0x17, 0x84, 0xc9, 0x7c, // }  HMAC-SHA1 fingerprint
3825            0x82, 0x92, 0xc2, 0x75, // }
3826            0xbf, 0xe3, 0xed, 0x41, // }
3827            0x80, 0x28, 0x00, 0x04, //    FINGERPRINT attribute header
3828            0xc8, 0xfb, 0x0b, 0x4c, //    CRC32 fingerprint
3829        ];
3830
3831        let msg = Message::from_bytes(&data).unwrap();
3832        assert!(msg.has_class(MessageClass::Success));
3833        assert!(msg.has_method(BINDING));
3834        assert_eq!(msg.transaction_id(), 0xb7e7_a701_bc34_d686_fa87_dfae.into());
3835        let mut builder = Message::builder(
3836            MessageType::from_class_method(MessageClass::Success, BINDING),
3837            msg.transaction_id(),
3838            MessageWriteVec::new(),
3839        );
3840
3841        // SOFTWARE
3842        assert!(msg.has_attribute(Software::TYPE));
3843        let raw = msg.raw_attribute(Software::TYPE).unwrap();
3844        assert!(Software::try_from(&raw).is_ok());
3845        let software = Software::try_from(&raw).unwrap();
3846        assert_eq!(software.software(), "test vector");
3847        builder.add_attribute(&software).unwrap();
3848
3849        // XOR_MAPPED_ADDRESS
3850        assert!(msg.has_attribute(XorMappedAddress::TYPE));
3851        let raw = msg.raw_attribute(XorMappedAddress::TYPE).unwrap();
3852        assert!(XorMappedAddress::try_from(&raw).is_ok());
3853        let xor_mapped_addres = XorMappedAddress::try_from(&raw).unwrap();
3854        assert_eq!(
3855            xor_mapped_addres.addr(msg.transaction_id()),
3856            "[2001:db8:1234:5678:11:2233:4455:6677]:32853"
3857                .parse()
3858                .unwrap()
3859        );
3860        builder.add_attribute(&xor_mapped_addres).unwrap();
3861
3862        // MESSAGE_INTEGRITY
3863        let credentials = MessageIntegrityCredentials::ShortTerm(ShortTermCredentials {
3864            password: "VOkJxbRl1RmTxUk/WvJxBt".to_owned(),
3865        });
3866        assert!(matches!(
3867            msg.validate_integrity(&credentials),
3868            Ok(IntegrityAlgorithm::Sha1)
3869        ));
3870        builder
3871            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3872            .unwrap();
3873
3874        // FINGERPRINT is checked by Message::from_bytes() when present
3875        assert!(msg.has_attribute(Fingerprint::TYPE));
3876        builder.add_fingerprint().unwrap();
3877
3878        // assert that we produce the same output as we parsed in this case
3879        let mut msg_data = builder.finish();
3880        // match the padding bytes with the original
3881        msg_data[35] = 0x20;
3882        assert_eq!(msg_data[..64], data[..64]);
3883    }
3884
3885    #[test]
3886    fn rfc5769_vector4() {
3887        let _log = crate::tests::test_init_log();
3888        // https://tools.ietf.org/html/rfc5769#section-2.4
3889        let data = vec![
3890            0x00, 0x01, 0x00, 0x60, //    Request type and message length
3891            0x21, 0x12, 0xa4, 0x42, //    Magic cookie
3892            0x78, 0xad, 0x34, 0x33, // }
3893            0xc6, 0xad, 0x72, 0xc0, // }  Transaction ID
3894            0x29, 0xda, 0x41, 0x2e, // }
3895            0x00, 0x06, 0x00, 0x12, //    USERNAME attribute header
3896            0xe3, 0x83, 0x9e, 0xe3, // }
3897            0x83, 0x88, 0xe3, 0x83, // }
3898            0xaa, 0xe3, 0x83, 0x83, // }  Username value (18 bytes) and padding (2 bytes)
3899            0xe3, 0x82, 0xaf, 0xe3, // }
3900            0x82, 0xb9, 0x00, 0x00, // }
3901            0x00, 0x15, 0x00, 0x1c, //    NONCE attribute header
3902            0x66, 0x2f, 0x2f, 0x34, // }
3903            0x39, 0x39, 0x6b, 0x39, // }
3904            0x35, 0x34, 0x64, 0x36, // }
3905            0x4f, 0x4c, 0x33, 0x34, // }  Nonce value
3906            0x6f, 0x4c, 0x39, 0x46, // }
3907            0x53, 0x54, 0x76, 0x79, // }
3908            0x36, 0x34, 0x73, 0x41, // }
3909            0x00, 0x14, 0x00, 0x0b, //    REALM attribute header
3910            0x65, 0x78, 0x61, 0x6d, // }
3911            0x70, 0x6c, 0x65, 0x2e, // }  Realm value (11 bytes) and padding (1 byte)
3912            0x6f, 0x72, 0x67, 0x00, // }
3913            0x00, 0x08, 0x00, 0x14, //    MESSAGE-INTEGRITY attribute header
3914            0xf6, 0x70, 0x24, 0x65, // }
3915            0x6d, 0xd6, 0x4a, 0x3e, // }
3916            0x02, 0xb8, 0xe0, 0x71, // }  HMAC-SHA1 fingerprint
3917            0x2e, 0x85, 0xc9, 0xa2, // }
3918            0x8c, 0xa8, 0x96, 0x66, // }
3919        ];
3920
3921        let msg = Message::from_bytes(&data).unwrap();
3922        assert!(msg.has_class(MessageClass::Request));
3923        assert!(msg.has_method(BINDING));
3924        assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
3925        let mut builder = Message::builder(
3926            MessageType::from_class_method(MessageClass::Request, BINDING),
3927            msg.transaction_id(),
3928            MessageWriteVec::new(),
3929        );
3930
3931        let username = stringprep::saslprep("\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}")
3932            .unwrap()
3933            .into_owned();
3934        let password = stringprep::saslprep("The\u{00AD}M\u{00AA}tr\u{2168}")
3935            .unwrap()
3936            .into_owned();
3937        trace!("password: {password:?}");
3938
3939        let long_term = LongTermKeyCredentials {
3940            username,
3941            password,
3942            realm: "example.org".to_owned(),
3943        };
3944        // USERNAME
3945        assert!(msg.has_attribute(Username::TYPE));
3946        let raw = msg.raw_attribute(Username::TYPE).unwrap();
3947        assert!(Username::try_from(&raw).is_ok());
3948        let username = Username::try_from(&raw).unwrap();
3949        assert_eq!(username.username(), &long_term.username);
3950        builder.add_attribute(&username).unwrap();
3951
3952        // NONCE
3953        let expected_nonce = "f//499k954d6OL34oL9FSTvy64sA";
3954        assert!(msg.has_attribute(Nonce::TYPE));
3955        let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
3956        assert!(Nonce::try_from(&raw).is_ok());
3957        let nonce = Nonce::try_from(&raw).unwrap();
3958        assert_eq!(nonce.nonce(), expected_nonce);
3959        builder.add_attribute(&nonce).unwrap();
3960
3961        // REALM
3962        assert!(msg.has_attribute(Realm::TYPE));
3963        let raw = msg.raw_attribute(Realm::TYPE).unwrap();
3964        assert!(Realm::try_from(&raw).is_ok());
3965        let realm = Realm::try_from(&raw).unwrap();
3966        assert_eq!(realm.realm(), long_term.realm());
3967        builder.add_attribute(&realm).unwrap();
3968
3969        // MESSAGE_INTEGRITY
3970        let credentials = MessageIntegrityCredentials::LongTerm(long_term);
3971        assert!(matches!(
3972            msg.validate_integrity(&credentials),
3973            Ok(IntegrityAlgorithm::Sha1)
3974        ));
3975        builder
3976            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha1)
3977            .unwrap();
3978
3979        assert_eq!(builder.finish()[4..], data[4..]);
3980    }
3981
3982    #[test]
3983    fn rfc8489_vector1() {
3984        let _log = crate::tests::test_init_log();
3985        // https://www.rfc-editor.org/rfc/rfc8489#appendix-B.1
3986        // https://www.rfc-editor.org/errata/eid6268
3987        let data = vec![
3988            0x00, 0x01, 0x00, 0x90, //     Request type and message length
3989            0x21, 0x12, 0xa4, 0x42, //     Magic cookie
3990            0x78, 0xad, 0x34, 0x33, //  }
3991            0xc6, 0xad, 0x72, 0xc0, //  }  Transaction ID
3992            0x29, 0xda, 0x41, 0x2e, //  }
3993            0x00, 0x1e, 0x00, 0x20, //     USERHASH attribute header
3994            0x4a, 0x3c, 0xf3, 0x8f, //  }
3995            0xef, 0x69, 0x92, 0xbd, //  }
3996            0xa9, 0x52, 0xc6, 0x78, //  }
3997            0x04, 0x17, 0xda, 0x0f, //  }  Userhash value (32 bytes)
3998            0x24, 0x81, 0x94, 0x15, //  }
3999            0x56, 0x9e, 0x60, 0xb2, //  }
4000            0x05, 0xc4, 0x6e, 0x41, //  }
4001            0x40, 0x7f, 0x17, 0x04, //  }
4002            0x00, 0x15, 0x00, 0x29, //     NONCE attribute header
4003            0x6f, 0x62, 0x4d, 0x61, //  }
4004            0x74, 0x4a, 0x6f, 0x73, //  }
4005            0x32, 0x41, 0x41, 0x41, //  }
4006            0x43, 0x66, 0x2f, 0x2f, //  }
4007            0x34, 0x39, 0x39, 0x6b, //  }  Nonce value and padding (3 bytes)
4008            0x39, 0x35, 0x34, 0x64, //  }
4009            0x36, 0x4f, 0x4c, 0x33, //  }
4010            0x34, 0x6f, 0x4c, 0x39, //  }
4011            0x46, 0x53, 0x54, 0x76, //  }
4012            0x79, 0x36, 0x34, 0x73, //  }
4013            0x41, 0x00, 0x00, 0x00, //  }
4014            0x00, 0x14, 0x00, 0x0b, //     REALM attribute header
4015            0x65, 0x78, 0x61, 0x6d, //  }
4016            0x70, 0x6c, 0x65, 0x2e, //  }  Realm value (11 bytes) and padding (1 byte)
4017            0x6f, 0x72, 0x67, 0x00, //  }
4018            0x00, 0x1d, 0x00, 0x04, //    PASSWORD-ALGORITHM attribute header
4019            0x00, 0x02, 0x00, 0x00, //    PASSWORD-ALGORITHM value (4 bytes)
4020            0x00, 0x1c, 0x00, 0x20, //    MESSAGE-INTEGRITY-SHA256 attribute header
4021            0xb5, 0xc7, 0xbf, 0x00, // }
4022            0x5b, 0x6c, 0x52, 0xa2, // }
4023            0x1c, 0x51, 0xc5, 0xe8, // }
4024            0x92, 0xf8, 0x19, 0x24, // }  HMAC-SHA256 value
4025            0x13, 0x62, 0x96, 0xcb, // }
4026            0x92, 0x7c, 0x43, 0x14, // }
4027            0x93, 0x09, 0x27, 0x8c, // }
4028            0xc6, 0x51, 0x8e, 0x65, // }
4029        ];
4030        let msg = Message::from_bytes(&data).unwrap();
4031        assert!(msg.has_class(MessageClass::Request));
4032        assert!(msg.has_method(BINDING));
4033        assert_eq!(msg.transaction_id(), 0x78ad_3433_c6ad_72c0_29da_412e.into());
4034        let mut builder = Message::builder(
4035            MessageType::from_class_method(MessageClass::Request, BINDING),
4036            msg.transaction_id(),
4037            MessageWriteVec::new(),
4038        );
4039
4040        let opaque = precis_profiles::OpaqueString::new();
4041        let username = opaque
4042            .prepare("\u{30DE}\u{30C8}\u{30EA}\u{30C3}\u{30AF}\u{30B9}")
4043            .unwrap()
4044            .into_owned();
4045        let orig_password = "The\u{00AD}M\u{00AA}tr\u{2168}";
4046        trace!("password: {orig_password:?}");
4047        /*
4048        let additional_password = opaque
4049            .additional_mapping_rule(orig_password)
4050            .unwrap()
4051            .into_owned();
4052        trace!("password (additional): {additional_password}");
4053        let normalized_password = opaque
4054            .normalization_rule(orig_password)
4055            .unwrap()
4056            .into_owned();
4057        trace!("password (normalized): {normalized_password}");
4058        let additional_then_normalized_password = opaque
4059            .normalization_rule(&additional_password)
4060            .unwrap()
4061            .into_owned();
4062        trace!("password (additional-then-normalized): {additional_then_normalized_password}");
4063        let normalized_then_additional_password = opaque
4064            .additional_mapping_rule(&normalized_password)
4065            .unwrap()
4066            .into_owned();
4067        trace!("password (normalized-then-additional): {normalized_then_additional_password}");
4068        */
4069        let sasl_password = stringprep::saslprep(orig_password).unwrap().into_owned();
4070        trace!("password (saslprep): {sasl_password}");
4071
4072        // XXX: should really be the OpaqueString value however that does not correctly remove
4073        // \u{00AD} that SASLprep did as required by RFC8489.
4074        let long_term = LongTermKeyCredentials {
4075            username: username.clone(),
4076            password: sasl_password.clone(),
4077            realm: "example.org".to_owned(),
4078        };
4079        // USERHASH
4080        assert!(msg.has_attribute(Userhash::TYPE));
4081        let raw = msg.raw_attribute(Userhash::TYPE).unwrap();
4082        assert!(Userhash::try_from(&raw).is_ok());
4083        let userhash = Userhash::try_from(&raw).unwrap();
4084        builder.add_attribute(&userhash).unwrap();
4085
4086        // NONCE
4087        let expected_nonce = "obMatJos2AAACf//499k954d6OL34oL9FSTvy64sA";
4088        assert!(msg.has_attribute(Nonce::TYPE));
4089        let raw = msg.raw_attribute(Nonce::TYPE).unwrap();
4090        assert!(Nonce::try_from(&raw).is_ok());
4091        let nonce = Nonce::try_from(&raw).unwrap();
4092        assert_eq!(nonce.nonce(), expected_nonce);
4093        builder.add_attribute(&nonce).unwrap();
4094
4095        // REALM
4096        assert!(msg.has_attribute(Realm::TYPE));
4097        let raw = msg.raw_attribute(Realm::TYPE).unwrap();
4098        assert!(Realm::try_from(&raw).is_ok());
4099        let realm = Realm::try_from(&raw).unwrap();
4100        assert_eq!(realm.realm(), long_term.realm);
4101        builder.add_attribute(&realm).unwrap();
4102
4103        // PASSWORD_ALGORITHM
4104        assert!(msg.has_attribute(PasswordAlgorithm::TYPE));
4105        let raw = msg.raw_attribute(PasswordAlgorithm::TYPE).unwrap();
4106        assert!(PasswordAlgorithm::try_from(&raw).is_ok());
4107        let algo = PasswordAlgorithm::try_from(&raw).unwrap();
4108        assert_eq!(algo.algorithm(), PasswordAlgorithmValue::SHA256);
4109        builder.add_attribute(&algo).unwrap();
4110
4111        // MESSAGE_INTEGRITY_SHA256
4112        /*
4113        for pass in [
4114            orig_password.to_owned(),
4115            sasl_password,
4116            normalized_password,
4117            additional_password,
4118            additional_then_normalized_password,
4119            normalized_then_additional_password,
4120        ] {
4121            let long_term = LongTermCredentials {
4122                username: username.clone(),
4123                password: pass,
4124                realm: "example.org".to_owned(),
4125            };
4126            trace!("long term: {long_term:?}");
4127            let credentials = MessageIntegrityCredentials::LongTerm(long_term);
4128            trace!("{:?}", msg.validate_integrity(&credentials));
4129        }
4130        */
4131        trace!("long term: {long_term:?}");
4132        let credentials = MessageIntegrityCredentials::LongTerm(long_term);
4133        assert!(matches!(
4134            msg.validate_integrity(&credentials),
4135            Ok(IntegrityAlgorithm::Sha256)
4136        ));
4137        builder
4138            .add_message_integrity(&credentials, IntegrityAlgorithm::Sha256)
4139            .unwrap();
4140
4141        assert_eq!(builder.finish()[4..], data[4..]);
4142    }
4143}