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