component.rs

 1// Copyright (c) 2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
 2//
 3// This Source Code Form is subject to the terms of the Mozilla Public
 4// License, v. 2.0. If a copy of the MPL was not distributed with this
 5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
 6
 7use crate::helpers::PlainText;
 8use sha1::Sha1;
 9use digest::Digest;
10
11generate_element!(
12    /// The main authentication mechanism for components.
13    Handshake, "handshake", COMPONENT,
14    text: (
15        /// If Some, contains the hex-encoded SHA-1 of the concatenation of the
16        /// stream id and the password, and is used to authenticate against the
17        /// server.
18        ///
19        /// If None, it is the successful reply from the server, the stream is now
20        /// fully established and both sides can now exchange stanzas.
21        data: PlainText<Option<String>>
22    )
23);
24
25impl Handshake {
26    /// Creates a successful reply from a server.
27    pub fn new() -> Handshake {
28        Handshake {
29            data: None,
30        }
31    }
32
33    /// Creates an authentication request from the component.
34    pub fn from_password_and_stream_id(password: &str, stream_id: &str) -> Handshake {
35        let input = String::from(stream_id) + password;
36        let hash = Sha1::digest(input.as_bytes());
37        let content = format!("{:x}", hash);
38        Handshake {
39            data: Some(content),
40        }
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use try_from::TryFrom;
48    use minidom::Element;
49
50    #[cfg(target_pointer_width = "32")]
51    #[test]
52    fn test_size() {
53        assert_size!(Handshake, 12);
54    }
55
56    #[cfg(target_pointer_width = "64")]
57    #[test]
58    fn test_size() {
59        assert_size!(Handshake, 24);
60    }
61
62    #[test]
63    fn test_simple() {
64        let elem: Element = "<handshake xmlns='jabber:component:accept'/>".parse().unwrap();
65        let handshake = Handshake::try_from(elem).unwrap();
66        assert_eq!(handshake.data, None);
67
68        let elem: Element = "<handshake xmlns='jabber:component:accept'>Coucou</handshake>".parse().unwrap();
69        let handshake = Handshake::try_from(elem).unwrap();
70        assert_eq!(handshake.data, Some(String::from("Coucou")));
71    }
72
73    #[test]
74    fn test_constructors() {
75        let handshake = Handshake::new();
76        assert_eq!(handshake.data, None);
77
78        let handshake = Handshake::from_password_and_stream_id("123456", "sid");
79        assert_eq!(handshake.data, Some(String::from("9accec263ab84a43c6037ccf7cd48cb1d3f6df8e")));
80    }
81}