stun_rs/attributes/stun/
password_algorithms.rs

1use crate::attributes::stun::PasswordAlgorithm;
2use crate::attributes::{stunt_attribute, DecodeAttributeValue, EncodeAttributeValue};
3use crate::common::{check_buffer_boundaries, fill_padding_value, padding};
4use crate::context::{AttributeDecoderContext, AttributeEncoderContext};
5use crate::StunError;
6use std::sync::Arc;
7
8//  0                   1                   2                   3
9//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
10//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11//  |         Algorithm 1           | Algorithm 1 Parameters Length |
12//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13//  |                    Algorithm 1 Parameters (variable)
14//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15//  |         Algorithm 2           | Algorithm 2 Parameters Length |
16//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17//  |                    Algorithm 2 Parameters (variable)
18//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19//  |                                                             ...
20
21const PASSWORD_ALGORITHMS: u16 = 0x8002;
22
23/// The [`PasswordAlgorithms`] attribute may be present in requests and
24/// responses.  It contains the list of algorithms that the server can
25/// use to derive the long-term password.
26///
27/// # Examples
28///```rust
29/// # use stun_rs::attributes::stun::{PasswordAlgorithm, PasswordAlgorithms};
30/// # use stun_rs::{Algorithm, AlgorithmId};
31/// // Creates an empty password algorithms attribute
32/// let mut attr = PasswordAlgorithms::default();
33/// assert_eq!(attr.iter().count(), 0);
34///
35/// // Adds a password algorithm attribute
36/// attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)));
37/// assert_eq!(attr.iter().count(), 1);
38///```
39#[derive(Debug, Clone, PartialEq, Eq, Default)]
40pub struct PasswordAlgorithms {
41    algorithms: Arc<Vec<PasswordAlgorithm>>,
42}
43
44impl PasswordAlgorithms {
45    /// Adds a new password algorithm.
46    pub fn add(&mut self, algorithm: PasswordAlgorithm) {
47        Arc::get_mut(&mut self.algorithms).unwrap().push(algorithm);
48    }
49
50    /// Return the array of password attributes
51    pub fn password_algorithms(&self) -> &[PasswordAlgorithm] {
52        &self.algorithms
53    }
54
55    /// Returns an iterator over the passwords attributes.
56    pub fn iter(&self) -> impl Iterator<Item = &PasswordAlgorithm> {
57        self.algorithms.iter()
58    }
59}
60
61impl IntoIterator for PasswordAlgorithms {
62    type Item = PasswordAlgorithm;
63    type IntoIter = std::vec::IntoIter<PasswordAlgorithm>;
64
65    fn into_iter(self) -> Self::IntoIter {
66        self.algorithms.clone().as_ref().clone().into_iter()
67    }
68}
69
70impl From<Vec<PasswordAlgorithm>> for PasswordAlgorithms {
71    fn from(v: Vec<PasswordAlgorithm>) -> Self {
72        Self {
73            algorithms: Arc::new(v),
74        }
75    }
76}
77
78impl DecodeAttributeValue for PasswordAlgorithms {
79    fn decode(ctx: AttributeDecoderContext) -> Result<(Self, usize), StunError> {
80        let mut attr = PasswordAlgorithms::default();
81
82        let raw_msg = ctx.decoded_message();
83        let raw_value = ctx.raw_value();
84
85        let mut size = 0;
86        let mut total_size = 0;
87        while total_size < raw_value.len() {
88            total_size += padding(size);
89            check_buffer_boundaries(raw_value, total_size)?;
90            let attr_ctx =
91                AttributeDecoderContext::new(ctx.context(), raw_msg, &raw_value[total_size..]);
92            let (val, len) = PasswordAlgorithm::decode(attr_ctx)?;
93            attr.add(val);
94            total_size += len;
95            size = len;
96        }
97
98        Ok((attr, total_size))
99    }
100}
101
102impl EncodeAttributeValue for PasswordAlgorithms {
103    fn encode(&self, mut ctx: AttributeEncoderContext) -> Result<usize, StunError> {
104        let mut it = self.algorithms.iter().peekable();
105        let mut size = 0;
106
107        while let Some(attr) = it.next() {
108            let len;
109            {
110                let raw_msg = ctx.encoded_message();
111                let raw_value = ctx.raw_value_mut();
112                check_buffer_boundaries(raw_value, size)?;
113                let attr_ctx = AttributeEncoderContext::new(None, raw_msg, &mut raw_value[size..]);
114                len = attr.encode(attr_ctx)?;
115                size += len;
116            }
117            if it.peek().is_some() {
118                let padding = padding(len);
119                let padding_value = ctx.context().unwrap_or_default().padding();
120                let raw_value = ctx.raw_value_mut();
121                fill_padding_value(&mut raw_value[size..], padding, padding_value)?;
122                size += padding;
123            }
124        }
125
126        Ok(size)
127    }
128}
129
130impl crate::attributes::AsVerifiable for PasswordAlgorithms {}
131
132stunt_attribute!(PasswordAlgorithms, PASSWORD_ALGORITHMS);
133
134#[cfg(test)]
135mod tests {
136    use super::*;
137    use crate::error::StunErrorType;
138    use crate::StunAttribute;
139    use crate::{Algorithm, AlgorithmId};
140
141    #[test]
142    fn constructor() {
143        let mut attr = PasswordAlgorithms::default();
144        assert_eq!(attr.iter().count(), 0);
145
146        attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)));
147        assert_eq!(attr.iter().count(), 1);
148
149        attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::SHA256)));
150        assert_eq!(attr.iter().count(), 2);
151
152        let mut iter = attr.password_algorithms().iter();
153        let algorithm = iter.next().expect("Expected algorithm");
154        assert_eq!(algorithm.algorithm(), AlgorithmId::MD5);
155
156        let algorithm = iter.next().expect("Expected algorithm");
157        assert_eq!(algorithm.algorithm(), AlgorithmId::SHA256);
158
159        // No more attributes expected
160        assert!(iter.next().is_none());
161
162        let attributes = vec![
163            PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)),
164            PasswordAlgorithm::new(Algorithm::from(AlgorithmId::SHA256)),
165        ];
166        let attr_1 = PasswordAlgorithms::from(attributes);
167
168        assert_eq!(attr, attr_1);
169    }
170
171    #[test]
172    fn decode_password_algorithms_attribute_value() {
173        let dummy_msg = [];
174        let buffer = [];
175        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
176        let (attr, size) =
177            PasswordAlgorithms::decode(ctx).expect("Could not decode PasswordAlgorithms");
178        assert_eq!(attr.into_iter().len(), 0);
179        assert_eq!(size, 0);
180
181        let buffer = [0x00, 0x01, 0x00, 0x00];
182        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
183        let (attr, size) =
184            PasswordAlgorithms::decode(ctx).expect("Could not decode PasswordAlgorithms");
185        assert_eq!(attr.into_iter().len(), 1);
186        assert_eq!(size, 4);
187
188        let buffer = [0x00, 0x01, 0x00, 0x02, 0x01, 0x02];
189        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
190        let (attr, size) =
191            PasswordAlgorithms::decode(ctx).expect("Could not decode PasswordAlgorithms");
192        assert_eq!(attr.into_iter().len(), 1);
193        assert_eq!(size, 6);
194
195        // First algorithm attribute has 2 bytes of padding at the positions 6 and 7
196        let buffer = [
197            0x00, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x03,
198        ];
199        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
200        let (attr, size) =
201            PasswordAlgorithms::decode(ctx).expect("Could not decode PasswordAlgorithms");
202        assert_eq!(attr.into_iter().len(), 2);
203        assert_eq!(size, 13);
204    }
205
206    #[test]
207    fn decode_password_algorithms_attribute_value_error() {
208        let dummy_msg = [];
209        let buffer = [0x00, 0x01, 0x00, 0x01];
210        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
211        assert_eq!(
212            PasswordAlgorithms::decode(ctx).expect_err("Error expected"),
213            StunErrorType::SmallBuffer
214        );
215
216        let buffer = [0x00, 0x01, 0x00, 0x00, 0x23];
217        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
218        assert_eq!(
219            PasswordAlgorithms::decode(ctx).expect_err("Error expected"),
220            StunErrorType::SmallBuffer
221        );
222    }
223
224    #[test]
225    fn decode_password_algorithms_attribute() {
226        let dummy_msg = [];
227        let buffer = [0x00, 0x01, 0x00, 0x00];
228        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
229        let (attr, size) =
230            PasswordAlgorithms::decode(ctx).expect("Could not decode PasswordAlgorithms");
231        assert_eq!(size, 4);
232        let mut iter = attr.into_iter();
233        assert_eq!(iter.len(), 1);
234        let val = iter
235            .next()
236            .expect("Can not get password algorithm attribute");
237        assert_eq!(val.algorithm(), AlgorithmId::MD5);
238
239        let buffer = [0x00, 0x01, 0x00, 0x02, 0x01, 0x02];
240        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
241        let (attr, size) =
242            PasswordAlgorithms::decode(ctx).expect("Could not decode PasswordAlgorithms");
243        assert_eq!(size, 6);
244        let mut iter = attr.into_iter();
245        assert_eq!(iter.len(), 1);
246        let val = iter
247            .next()
248            .expect("Can not get password algorithm attribute");
249        assert_eq!(val.algorithm(), AlgorithmId::MD5);
250        assert_eq!(val.parameters(), Some([0x01, 0x02].as_slice()));
251
252        // First algorithm attribute has 2 bytes of padding
253        let buffer = [
254            0x00, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x03,
255        ];
256        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
257        let (attr, size) =
258            PasswordAlgorithms::decode(ctx).expect("Could not decode PasswordAlgorithms");
259        assert_eq!(size, 13);
260        let mut iter = attr.into_iter();
261        assert_eq!(iter.len(), 2);
262
263        let val = iter
264            .next()
265            .expect("Can not get password algorithm attribute");
266        assert_eq!(val.algorithm(), AlgorithmId::MD5);
267        assert_eq!(val.parameters(), Some([0x01, 0x02].as_slice()));
268
269        let val = iter
270            .next()
271            .expect("Can not get password algorithm attribute");
272        assert_eq!(val.algorithm(), AlgorithmId::SHA256);
273        assert_eq!(val.parameters(), Some([0x03].as_slice()));
274    }
275
276    #[test]
277    fn decode_password_algorithms_attribute_error() {
278        let dummy_msg = [];
279        let buffer = [0x00, 0x01, 0x00];
280        let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
281        let result = PasswordAlgorithms::decode(ctx);
282        assert_eq!(
283            result.expect_err("Error expected"),
284            StunErrorType::SmallBuffer
285        );
286    }
287
288    #[test]
289    fn encode_password_algorithms_attribute_value() {
290        let dummy_msg: [u8; 0] = [0x0; 0];
291        let mut buffer = [];
292        let attr = PasswordAlgorithms::default();
293        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
294        let result = attr.encode(ctx);
295        assert_eq!(result, Ok(0));
296
297        let mut buffer: [u8; 4] = [0x0; 4];
298        let mut attr = PasswordAlgorithms::default();
299        attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)));
300        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
301        let result = attr.encode(ctx);
302        let expected_buffer = [0x00, 0x01, 0x00, 0x00];
303        assert_eq!(result, Ok(4));
304        assert_eq!(&buffer[..], &expected_buffer[..]);
305
306        let mut buffer: [u8; 6] = [0x0; 6];
307        let mut attr = PasswordAlgorithms::default();
308        let params = [0x01, 0x02];
309        let algorithm = Algorithm::new(AlgorithmId::MD5, params.as_ref());
310        attr.add(PasswordAlgorithm::new(algorithm));
311        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
312        let result = attr.encode(ctx);
313        let expected_buffer = [0x00, 0x01, 0x00, 0x02, 0x01, 0x02];
314        assert_eq!(result, Ok(6));
315        assert_eq!(&buffer[..], &expected_buffer[..]);
316
317        // Add two PASSWORD-AGORITHM attributes, the first one must fill 2 bytes of padding
318        let mut buffer: [u8; 13] = [0x0; 13];
319        let mut attr = PasswordAlgorithms::default();
320        let algorithm = Algorithm::new(AlgorithmId::MD5, params.as_ref());
321        attr.add(PasswordAlgorithm::new(algorithm));
322
323        let params = [0x03];
324        let algorithm = Algorithm::new(AlgorithmId::SHA256, params.as_ref());
325        attr.add(PasswordAlgorithm::new(algorithm));
326        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
327        let result = attr.encode(ctx);
328        let expected_buffer = [
329            0x00, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x03,
330        ];
331        assert_eq!(result, Ok(13));
332        assert_eq!(&buffer[..], &expected_buffer[..]);
333    }
334
335    #[test]
336    fn encode_password_algorithms_attribute_value_error() {
337        let dummy_msg: [u8; 0] = [0x0; 0];
338        let mut buffer = [];
339        let mut attr = PasswordAlgorithms::default();
340        attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)));
341        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
342        let result = attr.encode(ctx);
343        assert_eq!(
344            result.expect_err("Error expected"),
345            StunErrorType::SmallBuffer
346        );
347
348        let mut buffer: [u8; 3] = [0x0; 3];
349        let mut attr = PasswordAlgorithms::default();
350        attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)));
351        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
352        let result = attr.encode(ctx);
353        assert_eq!(
354            result.expect_err("Error expected"),
355            StunErrorType::SmallBuffer
356        );
357    }
358
359    #[test]
360    fn encode_password_algorithms_attribute() {
361        let dummy_msg: [u8; 0] = [];
362        let mut buffer = [];
363        let attr = PasswordAlgorithms::default();
364        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
365        let result = attr.encode(ctx);
366        let expected_buffer: [u8; 0] = [];
367        assert_eq!(result, Ok(0));
368        assert_eq!(&buffer[..], &expected_buffer[..]);
369
370        let mut buffer: [u8; 4] = [0x0; 4];
371        let mut attr = PasswordAlgorithms::default();
372        attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)));
373        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
374        let result = attr.encode(ctx);
375        let expected_buffer = [0x00, 0x01, 0x00, 0x00];
376        assert_eq!(result, Ok(4));
377        assert_eq!(&buffer[..], &expected_buffer[..]);
378
379        let mut buffer: [u8; 13] = [0x0; 13];
380        let params = [0x01, 0x02];
381        let mut attr = PasswordAlgorithms::default();
382        let algorithm = Algorithm::new(AlgorithmId::MD5, params.as_ref());
383        attr.add(PasswordAlgorithm::new(algorithm));
384
385        let params = [0x03];
386        let algorithm = Algorithm::new(AlgorithmId::SHA256, params.as_ref());
387        attr.add(PasswordAlgorithm::new(algorithm));
388
389        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
390        let result = attr.encode(ctx);
391        let expected_buffer = [
392            0x00, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x03,
393        ];
394        assert_eq!(result, Ok(13));
395        assert_eq!(&buffer[..], &expected_buffer[..]);
396    }
397
398    #[test]
399    fn encode_password_algorithms_attribute_error() {
400        let dummy_msg: [u8; 0] = [0x0; 0];
401
402        let mut buffer: [u8; 3] = [0x0; 3];
403        let mut attr = PasswordAlgorithms::default();
404        attr.add(PasswordAlgorithm::new(Algorithm::from(AlgorithmId::MD5)));
405        let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
406        let result = attr.encode(ctx);
407        assert_eq!(
408            result.expect_err("Error expected"),
409            StunErrorType::SmallBuffer
410        );
411    }
412
413    #[test]
414    fn password_algorithms_attribute() {
415        let attr = StunAttribute::PasswordAlgorithms(PasswordAlgorithms::default());
416        assert!(attr.is_password_algorithms());
417        assert!(attr.as_password_algorithms().is_ok());
418        assert!(attr.as_unknown().is_err());
419
420        assert!(!attr.attribute_type().is_comprehension_required());
421        assert!(attr.attribute_type().is_comprehension_optional());
422
423        let dbg_fmt = format!("{:?}", attr);
424        assert_eq!(
425            "PasswordAlgorithms(PasswordAlgorithms { algorithms: [] })",
426            dbg_fmt
427        );
428    }
429}